前言
在做项目的过程中,需要用到文件上传功能,且需要支持单个/批量文件上传,最好是不会进行页面跳转的、局部刷新的异步请求。在查阅的一些资料和实现后,选择了一种相对优雅和简洁的方式。
Maven 导入 JQuery 依赖简化开发
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.5.1</version>
</dependency>
HTML 代码
<body>
<form enctype="multipart/form-data">
请选择要上传的文件:<br/>
<input id="file" type="file" multiple="multiple"/><br/>
<input id="submit_btn" type="button" value="上传"/>
</form>
</body>
JS 代码
<script th:src="@{/webjars/bootstrap/4.5.2/js/bootstrap.min.js}"></script>
<script inline="javascript">
$("#submit_btn").click(function () {
var formData = new FormData();
var fileobjs = $("#file")[0].files; // $("#file")[0]将jquery对象转换为dom对象,使用jquery的方法.get(0)也可以
for (var i = 0; i < fileobjs.length; i++) {
formData.append("imgs", fileobjs[i]); // append方法使用相同键追加元素,最后会被输出为MultipartFile数组
}
$.ajax({
type: 'post',
url: "/upload",
async: false, // 设置为同步执行
data: formData,
processData : false, // 禁止去处理发送的数据,对data参数进行序列化处理时须设置
contentType : false, // 禁止去设置Content-Type请求头
success: function (res) {
alert(res);
},
error: function (e) {
}
})
});
</script>
Java 后端代码
@Controller
public class UploadController {
private static final Logger LOGGER = LoggerFactory.getLogger(UploadController.class);
@PostMapping("/upload")
@ResponseBody
public String upload(@RequestParam("imgs") List<MultipartFile> files, HttpSession session) {
if (files.isEmpty())
return "上传失败,请选择文件";
try {
String filePath = ResourceUtils.getURL("classpath:").getPath()+"/users/"; // 接收到的文件会存放在 target/classes/users/ 下
File fp = new File(filePath);
if(!fp.exists())
fp.mkdir();
for (MultipartFile f : files) {
String uuid = UUID.randomUUID().toString().replace("-", "");
String fileName = f.getOriginalFilename();
String suffix = fileName.substring(fileName.lastIndexOf("."));
File dest = new File(filePath, uuid + suffix);
f.transferTo(dest);
LOGGER.info("==upload success==");
}
return "上传成功";
} catch (Exception e) {
LOGGER.error(e.toString(), e);
}
return "上传失败";
}
}
补充知识
FormData 是 XMLHttpRequest Level 2 提供的一个接口对象,用以将数据编译成键值对,以便于XMLHttpRequest
来发送数据
主要用法:
将 form 表单元素的 name 与 value 进行组合,实现表单数据的序列化,从而减少表单元素的拼接,提高工作效率
使用该对象来模拟或处理表单并进行(异步)文件上传操作