Skip to content

关于多文件上传的解决方案[每天进步一点点系列] #30

Description

@stuxt

文件上传,是很常见的一个需求,项目中当我看设计稿有这个需求的时候并没有太在意,觉得这个东东司空见怪。

等到去看到这块实现的时候,发现这个跟之前的上传有一点点的差别,那就是要求一个表单同时上传两个或者多个文件。

理论上来说,表单提交设置多个不同的<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 以下的浏览器就不用考虑了。

当然,这其中如果是在不同域之间传输的话,也会有跨域的问题,因为这部分是在项目初始就解决了的,所以这里不做过多描述。

至此,多文件上传这个问题就解决了,但是如果需要考虑兼容性的小伙伴,还得看看其他兼容的解决方案哦。

参考:图片上传进阶 VS 京东户簿实战


每天进步一点点系列
第002篇

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions