Base64
Base64相关知识: https://zhuanlan.zhihu.com/p/141976797
文件上传
上传文件示例及生成最后的url可供访问
package com.kob.backend.controller.file;
import com.kob.backend.mapper.UserMapper;
import com.kob.backend.pojo.User;
import com.kob.backend.service.impl.utils.UserDetailsImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.util.Base64;
import java.util.UUID;
@RestController
@RequestMapping("/file")
public class UploadFileController {
@Value("${myfile.path}")
private String filePath;
@Autowired
private UserMapper userMapper;
@PostMapping("/uploadFile")
public void uploadFile(@RequestParam("file") MultipartFile multipartFile){
String fileName = multipartFile.getOriginalFilename();
String name = UUID.randomUUID().toString() + '-' + fileName;
File file = new File(filePath+name);
try {
//文件保存到服务器上
multipartFile.transferTo(file);
//映射到服务器的资源路径url,并保存到数据库中
String url = "https:///images/" + name;;
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
(UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
UserDetailsImpl userDetails = (UserDetailsImpl) usernamePasswordAuthenticationToken.getPrincipal();
User user = userDetails.getUser();
user.setPhoto(url);
userMapper.updateById(user);
} catch (IOException e) {
e.printStackTrace();
}
}
}
配置文件
myfile.path=/home/lcw/kob/images/
tips:配置nginx记得也要设置对应的路径重定向到对应的文件夹,否则会访问不到
获取文件
- 找到对应的文件,并生成base64编码返回给前端
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;
public class FileToBase64 {
public String encryptToBase64(String filePath) {
if (filePath == null) {
return null;
}
try {
byte[] b = Files.readAllBytes(Paths.get(filePath));
return Base64.getEncoder().encodeToString(b);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
- 后端将文件转换成二进制返回给前端,前端通过API生成 Blob URL,而后添加到对应的属性上
后端:
import org.apache.commons.io.IOUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class FileToBinaryConverter {
public static byte[] convertToBinary(String filePath) throws IOException {
File file = new File(filePath);
try (FileInputStream fis = new FileInputStream(file)) {
return IOUtils.toByteArray(fis);
} catch (IOException e) {
throw new IOException("无法读取文件:" + filePath, e);
}
}
}
前端通过 URL.createObjectURL() API 即可生成对应的Blob URL,以下是示例
var blob = new Blob([arrayBufferWithPNG], {type: "image/png"}),
url = URL.createObjectURL(blob),
img = new Image();
img.onload = function() {
URL.revokeObjectURL(this.src); // clean-up memory
document.body.appendChild(this); // add image to DOM
}
img.src = url; // can now "stream" the bytes
- 将文件存储到服务器上,通过路径映射的方式访问到服务器上的文件,也是最常用的
文件上传示例代码里有一部分就是做了这件事,关键代码为:
//映射到服务器的资源路径url,并保存到数据库中
String url = "https:///images/" + name;
其中,"https://app5608.acapp.acwing.com.cn/" 是访问到服务器的url,images/ 和后面的 name 变量都是要映射到服务器上的路径,这个要根据中间价 nginx 配置来决定
如何让文件不重复?
思路:生成每个文件的 MD5 值,存储到数据库中,下次只需要判断新添加的文件生成的 MD5 值在数据库中是否出现即可解决文件重复的问题
如何让文件不重名?
思路:
- 可以生成 UUID+文件名 的方式解决
- 可以生成 UUID+ 字段id 的的方式解决
字段id为数据库中图片表中的字段id