stuxt.github.io
stuxt.github.io copied to clipboard
关于多文件上传的解决方案[每天进步一点点系列]
文件上传,是很常见的一个需求,项目中当我看设计稿有这个需求的时候并没有太在意,觉得这个东东司空见怪。
等到去看到这块实现的时候,发现这个跟之前的上传有一点点的差别,那就是要求一个表单同时上传两个或者多个文件。
理论上来说,表单提交设置多个不同的<input type=“file”/>,很容易就能实现的。但真是图样图森破啊,这只是表面看上去是这样的,于是我就写了一个demo试了一下,从network的记录来看并不是预想中的那样,其实是每个文件的上传都会单个的请求发送,而并不是一个请求同时发送多个文件的。
这里说的是异步的表单提交方式,因为用form的action来实现的话,表单的提交是会有页面的刷新和跳转的。所以用的是异步的post请求方式。
怎么办呢?于是各种搜索和骚扰同事需求办法。
最终使用了FormData的方式实现了这种需求。
核心代码如下:
upload.vue
//hrml代码片段
……
<el-form-item label="文件1" prop="File1" :label-width="formLabelWidth">
<input type="file" name="file1" @change="getFile($event)" ref="fileInput"/>
</el-form-item>
<el-form-item label="文件2" prop="File2" :label-width="formLabelWidth">
<input type="file" name="file2" @change="getFile($event)" ref="fileInput"/>
</el-form-item>
……
//js代码片段
let f = new FormData();
f.append('token', this.ruleForm.token);
f.append('id', this.ruleForm.id);
……
f.append('file1', this.ruleForm.file1);
f.append('file2', this.ruleForm.file2);
……
this.upload(f).then(()=> {
this.showSuccessMsg("上传成功!");
}).catch(() => {
this.showErrorMsg("上传失败,请重试!");
});
以上代码中,文件需要通过 FormData 来承载并通过 xhr 发送给服务端,FormData 会有哪些隐患呢?来看一下 XHR 的发展历程。
XHR 一开始只是微软浏览器提供的一个接口,后来各大浏览器纷纷效仿也提供了这个接口,再后来W3C对它进行了标准化,提出了 XHR 标准。XHR 标准又分为Level 1 和 Level 2。
XHR Level 1 中,XHR 有以下三个缺点:
- 只支持文本数据的传送,无法用来读取和上传二进制文件。
- 传送和接收数据时,没有进度信息,只能提示有没有完成。
- 受到“同域限制”(Same Origin Policy),只能向同一域名的服务器请求数据。
XHR Level 2 新版本针对老版本做出了大幅改进:
- 可以设置 http 请求的时限。
- 可以使用 FormData 对象管理表单数据。
- 可以上传文件。
- 可以请求不同域名下的数据(跨域请求)。
- 可以获取服务器端的二进制数据。
- 可以获得数据传输的进度信息。
FormData 参数为 XHR Level 2 中新增接口,所以会存在或多或少的兼容性隐患问题,兼容下请到caniuse.com查看。
根据以上的兼容性,基本上 IE10 以下的浏览器就不用考虑了。
当然,这其中如果是在不同域之间传输的话,也会有跨域的问题,因为这部分是在项目初始就解决了的,所以这里不做过多描述。
至此,多文件上传这个问题就解决了,但是如果需要考虑兼容性的小伙伴,还得看看其他兼容的解决方案哦。
每天进步一点点系列 第002篇