1 概述
文件上传的基本原理:通过MultipartFile接收前端上传的文件,然后将文件以字节流的形式发送到存储的服务器。
ps:springboot上传文件会创建一个临时目录,像这样的
2 上传至tomcat
2.1 配置tomcat
2.2 后端controller代码
获取到上传的文件,取文件名后缀,uuid+后缀名重命名文件,上传到tomcat。
@RestController
@RequestMapping("/upload")
public class UploadController {
// 文件存储位置,在tomcat的conf文件配置服务端口号
private final static String FILESERVER="http://127.0.0.1:8090/upload/";
@PostMapping("/file")
public Map<String, Object> imgUpload(MultipartFile file){
HashMap<String, Object> result = new HashMap<>();
// 1.获取上传文件的后缀名
String originalFilename = file.getOriginalFilename();
String extendsName = originalFilename.substring(originalFilename.lastIndexOf("."));
// 2.文件重命名
String uuid = UUID.randomUUID().toString();
String newFileName = uuid.concat(extendsName);
// 3.发送文件至tomcat服务器
Client client = Client.create(); // 使用jersey依赖完成跨域传输文件
WebResource resource = client.resource(FILESERVER + newFileName);
try {
resource.put(String.class, file.getBytes());
} catch (IOException e) {
result.put("status", "error");
result.put("msg", "文件上传失败,查看原因:"+e.getMessage());
return result;
}
result.put("status", "success");
result.put("url", FILESERVER + newFileName);
return result;
}
}
2.3 测试结果
url就是文件路径,可以在前端回显。
postman的测试结果,因为配置的tomcat是本地的,所以在本地的tomcat目录中也能看见文件
3 上传至阿里云
在实际项目中,通常采用的是微服务架构,后端会有多个服务,像“上传文件”这种比较常用的功能通常会使用第三方的服务,比如说阿里云的。
而且上传文件时,文件是存储在阿里云服务器的。前端上传图片时,需要从服务端获取policy,然后再通过policy上传图片,回显图片的url地址。而后端只要返回policy即可,前端拿到policy后会直接上传至阿里云,就不用再发到后端服务了。
3.1 阿里云对象存储oss服务配置
3.2 后端获取policy
@PostMapping("/ali/file")
public Map<String, Object> getAliPolicy(){
HashMap<String, Object> result = new HashMap<>();
// 访问的阿里云地址
String host = "https://"+bucket+"."+endpoint;
// 设置上传到阿里云的文件前缀
String format = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
String dir = format + "/";
Map<String, String> respMap = null;
// 创建ossClient实例
try {
long expireTime = 30;
long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
Date expiration = new Date(expireEndTime);
PolicyConditions policyConds = new PolicyConditions();
policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);
String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
byte[] binaryData = postPolicy.getBytes("utf-8");
String encodedPolicy = BinaryUtil.toBase64String(binaryData);
String postSignature = ossClient.calculatePostSignature(postPolicy);
respMap = new LinkedHashMap<>();
respMap.put("accessId", accessId);
respMap.put("policy", encodedPolicy);
respMap.put("signature", postSignature);
respMap.put("dir", dir);
respMap.put("host", host);
respMap.put("expire", String.valueOf(expireEndTime / 1000));
} catch (Exception e) {
result.put("status", "error");
result.put("msg", "文件上传失败,查看原因:"+e.getMessage());
}
result.put("status", "success");
result.put("data", respMap);
return result;
}
3.3 后端测试结果
前端拿到policy后即可上传文件。
4 补充
这篇博客主要还是作为自己从后端的角度实现“上传文件”功能的一个总结,还留下了一些坑,比如说配置以及前端的实现等等,这些内容以后再补上了。