大文件上传

150 阅读3分钟
业务背景

行员A培训中心->材料管理->新增材料
上传文件:不大于200M,限制格式为pdf、excel、word等

参考文章 juejin.cn/post/740748…

前端流程:

1、 读取本地的文件,读成一个文件对象

2、 使用slice对文件对象进行切割,得到Blob类型的文件对象

文件切片处理:固定数量&固定大小

  • 固定大小:文件最小按100kb进行分片,即文件大小/100kb
  • 固定数量:文件过大,则按100份进行分片,即文件大小/100片

3、 将Blob类型的文件对象转成FormData表单类型的对象

4、 发送post请求,上传到服务器

两种方式:

a.将FormData对象切片成一个一个的发送给后端,如果前一个切片上传成功,接着下一个切片,直到切片结束;切片上传失败,则取消上传
b.将文件切分为一个个切片,然后借助 http 的可并发性,同时上传多个切片。这样从原本传一个大文件,变成了并发传多个小的文件切片;另外由于是并发,传输到服务端的顺序可能会发生变化,因此我们还需要给每个切片记录顺序

第二点
核心就是利用 Blob.prototype.slice这个方法,它和数组的slice方法相似,但不是,文件的slice方法可以返回原文件的某个切片,将大文件对象进行切割得到小的Blob对象,由于后端无法识别Blob对象,所以需要转为前后端都能识别的FormData对象,在用post请求发送给后端
第四点
利用promise.all()并行将切片发送给后端,存在问题,一个切片失败,后端会将失败的文件进行合并

后端流程

1、接受前端传递的切片并解析切片得到数据

2、保存切片到某个文件夹

3、当接受到前端的合并请求后,开始合并切片

4、创建可写流,将所有的切片读成流类型并汇入到可写流中得到完整的文件资源

服务端负责接受前端传输的切片,并在接收到所有切片后合并所有切片

前端流程

5、 合并文件

两种方式:
a.前端在每个切片中都携带切片最大数量的信息,当服务端接受到这个数量的切片时自动合并。
b.也可以额外发一个请求,主动通知服务端进行切片的合并

这里采用第二种,发送请求,合并文件

6、计算进度条

a.一个切片上传成功后,数量加1,除以切片总数量,展示进度条

7、 断点续传

a.前端使用 localStorage 记录已上传的切片index
缺点:换个浏览器,失去记忆的功能

b.服务端保存已上传的切片 hash,前端每次上传前向服务端获取已上传的切片
这里采用第二种(后端思路:通过文件的hash值来判断服务器上是否存在该文件。如果该文件在服务器上不存在,则新建一个文件,否则继续上传该文件)

相关知识:

1、blob介绍
Blob 对象表示一个不可变、原始数据的类文件对象。它的数据可以按文本或二进制的格式进行读取,也可以转换成 ReadableStream 来用于数据操作。
当我们选中一个文件时,浏览器默认会帮我们将文件转成一个 Blob 对象, Blob 上自带一个 slice 方法,Blob.slice()接受的参数不是下标,而是起始字节最终字节
并且 slice 最终返回一个Blob对象