前言
通常我们在开发中,或多或少会接触到文件上传,而如今又是前后端分离的时代,所以就需要涉及ajax上传,本文用的为jquey,原生ajax比较麻烦,本文就不去涉及
一、CommonsMultipartResolver是什么?
CommonsMultipartResolver基于springmvc的文件上传的第三方工具,使用十分简单,几乎无需配置。它需要依赖于commons-fileupload,commons-io两个jar包
二、使用步骤
1.maven引入jar
代码如下(示例):
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.8.0</version>
</dependency>
其次,在spring-mvc配置文件下注册CommonsMultipartResolver,这里重点注意,bean的id被要求为multipartResolver,否则在业务层或controller层无法使用。
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="utf-8"/>
<property name="maxUploadSize" value="10485760000"/>
</bean>
上述只为简单配置,基本够用,分别为默认编码,最大上传大小,其余属性自查。
2.前端,jquery,使用FormData()
首先这是我的上传标识,也就是一个样式
大致思路就是,用户点击上传的标识后,js生成一个input type=‘file’的标签,并设置为隐藏,然后自主调用其点击事件即可,通常input一个标签只能选择多个,注意这里是一个按钮上传多个文件,标签加上属性multiple即可,让然多个标签上传也是同样的道理。标签隐藏加入style='display: none’即可
$("#upload").click(function () {
let upload = $("<input type='file' id='file' name='file' multiple style='display: none'>")
$("body").append(upload)
upload.click()
})
然后又继续绑定这个隐藏标签的点击事件,也就是调用后端接口
$("body").on("change", "#file", function () {
let formData = new FormData()
$.each(this.files, function (index, res) {
formData.append("files", res)
})
$.ajax({
url: 'photos/uploadPhotos',
method: 'post',
data: formData,
cache: false,//取消浏览器缓存,当发起一次请求后,会把获得的结果以缓存的形式进行存储,之后直接读取缓存,所以要设置为false
processData: false,//这是jquery特性,自动转换对象的形式上传的数据都会被转换为字符串的形式上传。当上传文件的时候,我们不需要这样转换,必须设置为false
contentType: false,//默认值:application/x-www-form-urlencoded但是在上传时我们需要的格式为multipart/form-data,因此不使用默认值,设置为false
success(res) {
if (res.code === 20000) {
alert("上传成功!")
setInterval(function () {
window.location.reload()
}, 1000)
} else {
alert("抱歉,上传失败,请重试!")
}
}
})
})
有人可能会奇怪为什么不去直接$("#file").click,这里又说道js的知识,这种方法绑定动态生成的标签,上述方法可以解决,但也只是其中一种解决方法,如果想继续深入了解其他,请参考大佬的文章解决使用JQuery或JS动态添加的元素无法绑定事件的问题
js内置FormData(),用来模拟表单,也就是可以向其中以Key-value的方式添加直接ajax提交到后端,十分方便
3.controller层
代码如下(示例):
@PostMapping("/uploadPhotos")
public Result uploadPhotos(@RequestParam("files") List<MultipartFile> multipartFiles) {
String path = "/usr/local/lib/tomcat/webapps/static/" + typeString + "/";
List<Photos> photos = new ArrayList<>();
for (MultipartFile photo : multipartFiles) {
String name = photo.getContentType();
String uuidName = UUID.randomUUID().toString().replace("-", "") + "." + name.substring(name.lastIndexOf("/") + 1);
File file = new File(path + uuidName);
try {
photo.transferTo(file);
} catch (IOException e) {
e.printStackTrace();
return ResultUtil.fail();
}
Photos p = new Photos();
p.setPath(path.substring(path.lastIndexOf("static") - 1) + uuidName);
p.setSize(photo.getSize());
p.setType(photo.getContentType());
photos.add(p);
}
return ResultUtil.success(photosService.inserPhotos(photos, type));
}
上述是我业务中的代码,忽略type参数,Photos类为图片的三种属性,用于插入数据库。下面依次解释
1.MultipartFile类: 前端一个input file也就是一个文件对应一个类,由于是多文件上传,因此我们使用List集合,springmvc的参数映射会自动帮我们封装好这些对象。
2.transferTo()方法 :参数为File类,也就是本地上传路径,一句代码就可转存,十分方便
总结
CommonsMultipartResolver使用起来及其方便,同时配合jquery达到很方便的效果,大致流程也就是这样。