Spring Boot 文件上传
原文链接:https://www.javaboy.org/2021/0415/servlet3.0-fileupload.html
码云地址:https://gitee.com/li-jie-jie/springboot0-study/tree/master
本地项目地址:D:\javalab\MyIDEAJavaSpring-Boot\spring-study\fileupload
1.两种文件解析方案
对于上传文件的请求,SpringMVC 中目前共有两种不同的解析方案:
-
StandardServletMultipartResolver 支持 Servlet3.0 中标准的文件上传方案,使用非常简单。可以直接通过 HttpServletRequest 自带的 getPart 方法获取上传文件并保存,这是一种标准的操作方式,这种方式也不用添加任何额外的依赖,只需要确保 Servlet 的版本在 3.0 之上即可。
-
CommonsMultipartResolver 则需要结合 Apache Commons fileupload 组件一起使用,这种方式兼容低版本的 Servlet。
本文讲的是:StandardServletMultipartResolver。
2.后端代码:
注意事项:
- 保存的文件不能重名,这里使用UUID.randomUUID()来保证不重名
- 一个文件夹如果保存太多资源,会导致文件夹打开太慢,这里使用日期来分类。
2.1 controller层
@RestController
@RequestMapping("/file")
public class FileUploadController {
/**
* 通过时间创建不同的文件夹,当天下载的文件放在当天的文件夹下,注意后面的“/”不能少,
*/
private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd/");
@PostMapping("/load")
public String fileUpload(MultipartFile file, HttpServletRequest request) {
String format = simpleDateFormat.format(new Date());
//获取服务器存储的真实路径
String realPath = request.getServletContext().getRealPath("/img") + format;
//如果文件夹不存在就创建
File folder = new File(realPath);
if (!folder.exists()) {
folder.mkdirs();
}
//获取上传的文件名
String oldName = file.getOriginalFilename();
//用随机产生的UID+源文件名的后缀,作为新的文件名
String newName = UUID.randomUUID().toString() + oldName.substring(oldName.lastIndexOf("."));
try {
//transferTo,中文转移,也就是把file转移到新的文件中。其实就是拷贝
file.transferTo(new File(folder, newName));
//返回请求地址url,通过这个地址就可以访问到上传的文件
String url = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + "/img"
+ format + newName;
return url;
} catch (IOException e) {
e.printStackTrace();
}
//上传失败就返回"error"
return "error";
}
}
使用这种方式我们什么都不用配了,spring boot已经帮我们配置好了。但是我们想要配置限制文件大小等,要怎么配置呢?我们可以在yml配置文件中进行配置。
2.2 yml配置
spring:
servlet:
multipart:
max-file-size: 1MB #上传单个文件最大容量,注意MB单位是大写的
max-request-size: 10MB #最大请求容量
enabled: true #是否启用StandardServletMultipartResolver
location: #上传文件的临时目录,如果上传的文件很大的话,就需要一个临时目录.
resolve-lazily: false #是否支持 multipart 上传文件时懒加载
file-size-threshold: 0 #支持文件写入磁盘
3. 前端页面
前端这里有两种方式上传文件:
- from表单
- jquery的ajax
3.1from表单上传文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/file/load" enctype="multipart/form-data" method="post">
<input type="file" name="file">
<input type="submit" value="提交">
</form>
</body>
</html>
3.2 Ajax上传文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!-- 注意script不能自结束-->
<script src="jquery-3.6.0.js"></script>
</head>
<body>
<div id="result"></div>
<input type="file" id="file">
<input type="button" value="上传" onclick="uploadFile()">
<script>
function uploadFile() {
// $('#file')是juery对象,加上[0]变为javaScript对象,然后获取到文件
var file = $('#file')[0].files[0]
//将文件添加到FormData
var formData = new FormData()
formData.append("file", file);
$.ajax({
type: 'post',
url: '/file/load',
processData: false,//把上传的数据转换成Java对象,默认为true
contentType: false,//设置请求头,要避免设置请求头,可能会破环里面的分隔符
data: formData,
success: function (msg) {
$("#result").html(msg);
}
})
}
</script>
</body>
</html>
这里我犯了一个错误script自结束,导致整个页面加载不出来。
<script src="jquery-3.6.0.js"/>
另外将jquery导入但是访问不到,这可能是target包中没有生成。把它删了重新启动项目即可。
4. 多文件上传
只要明白了单文件上传,多文件上传就很简单,
4.1controller层:
MultipartFile[]改为数组,然后遍历flie进行上传。
/**
* 多文件上传
*/
@PostMapping("/multipleLoad")
public void multipleFileUpload(MultipartFile[] files, HttpServletRequest request) {
String format = simpleDateFormat.format(new Date());
//获取服务器存储的真实路径
String realPath = request.getServletContext().getRealPath("/img") + format;
//如果文件夹不存在就创建
File folder = new File(realPath);
if (!folder.exists()) {
folder.mkdirs();
}
for (MultipartFile file : files) {
//获取上传的文件名
String oldName = file.getOriginalFilename();
//用随机产生的UID+源文件名的后缀,作为新的文件名
String newName = UUID.randomUUID().toString() + oldName.substring(oldName.lastIndexOf("."));
try {
//transferTo,中文转移,也就是把file转移到新的文件中。其实就是拷贝
file.transferTo(new File(folder, newName));
//返回请求地址url,通过这个地址就可以访问到上传的文件
String url = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() +
"/img"
+ format + newName;
System.out.println(url);
} catch (IOException e) {
e.printStackTrace();
}
}
}
4.2前端页面
<form action="/file/multipleLoad" enctype="multipart/form-data" method="post">
<input type="file" name="files" multiple>
<input type="submit" value="提交">
</form>
注意input标签要加上multiple属性表示可以选择多个文件