先废话一波~~
原本的多文件上传功能在选择文件时,只能通过同一范围的鼠标框选或者ctrl/shift多选取选择文件,这样选择文件很不灵活,而且在确定之后如果漏选了文件,再次点击上传按钮时会清空表单里的文件信息,只能重复之前的操作去选文件再加上漏选的文件,十分不方便。
所以在大部分网站上选择图片上传都是可以累加的,就是在第一次选择完文件点击确定后,第二次再点击上传按钮选文件会自动跟第一次的接在一起,然后展示在界面上,方便用户单独进行删除。文章的主旨就是在不用插件的情况下实现这样的效果。
实现
思考过程基本是:最后要得到的是文件数组MultipartFile[] → 页面ajax传递参数要为数组 → 把文件放到能灵活操作的js数组里 → 通过change方法能在选择文件后放到js数组 → FormData能灵活地把js数组里的对象封装成表单信息(FormData兼容ie8以上)。
<form enctype="multipart/form-data">
<input id="file" onchange="fileChange(this)" type="file" name="file" multiple>
</form>
记得要清空input file里面的信息,因为change是在input里的信息发生改变时才触发,如果没清空,在上传跟上一次操作一样的文件时,就不会触发方法。例如:选择了A文件,不小心点删除了,再次选择A文件就会失败。
//全局一个文件数组
var fileArray = new Array();
function fileChange(obj) {
$(obj.files).each(function(i, e){
fileArray.push(e);
});
//清空input file里的信息
$(obj).val('');
}
//展示添加的文件
function eachFileArray() {
var html ="";
$(fileArray).each(function(i, e){
html +='<span onclick="delFile('+i+')">'+e.name+'</span>'
});
return html;
}
splice是一个特别好用的方法,可以添加、修改、删除、插入,建议好好去看一下。在这是按下标去删除文件。
//点击删除文件
function delFile(index){
fileArray.splice(i,1);
}
最后是ajax上传文件和后台接收文件(Spring)
var formData = new FormData();
$(fileArray).each(function(i, e){
//这里设置的key是自定义的,作用是在后端获取时的指定(跟平常的form表单提交一样)
formData.append('files',e);
})
$.ajax({
url: "uploadFile",
type: "POST",
data: formData,
//停止jquery的深度序列化
traditional: true,
//不使用缓存,每次请求都从服务端获取
cache: false,
//停止转化成一个查询字符串
processData: false,
//不使用ajax的编码类型
contentType: false,
success: function (data) {
if (data.success) {
alert("上传成功");
}
}
});
控制层要用注解 RequestPart或者RequestParam标识文件数组(建议RequestPart),名字就是FormData里设置的key。
@ResponseBody
@PostMapping(value = "/uploadFile")
public Object uploadFile(@RequestPart(value = "files") MultipartFile[] files) {
//逻辑代码
...
}
结尾:个人感想(为何开始写博客)
第一次写博客,写得不好请多见谅。其实这个图片上传的需求,最早是在2017年6月左右我的第一家公司提的,那时刚进公司大概两个多月,一直都是在研究后端和数据库还稍微会点静态页面的小白,突然就要开始做全栈了(除了服务器),首先就被各种http协议之类的打败了,后面花了三天左右的时间去完成这个功能....
然后最近在用spring cloud重构公司的旧项目时,大佬要求全部多图片上传都加上这个功能,当时2018年11月了,离上次实现这个功能时已经过去1年半了,发现自己只记得有做过这件事,但完全想不起来实际是怎么样的,也找不到资料(懒鬼没有笔记),从此决定要用博客记录下那些有成就感的进步。