大文件切片上传

场景和定义

文件分片上传就是把文件分成一个个小块然后逐个上传,以文件的[md5]作为文件的唯一标识,这样即使上传过程中因某些原因中断了,等到下次再上传的时候,通过对比文件的md5来确认是否是相同文件,就可以在上次的基础上继续上传。

用到的知识点

files文件分片、计算MD5值(sparkMD5)、WebWorker

files文件分片

使用 file.slice将文件切片,然后使用 FileReader 读取 blob,API 为 readAsArrayBuffer,最后在FileReader.onload(e)读取完成的方法中,完成相应的逻辑

var blob = file.slice( start, end )  //start:开始位置,end:结束位置
var fileReader = new FileReader();
fileReader.readAsArrayBuffer( blob );
fileReader.onload = (e) => {
  ...
}

计算文件 MD5 值(sparkMD5)

使用spark-md5.js插件能快速计算文件的md5。

WebWorker

我们都知道道JavaScript是单线程的,阮一峰的文章里面说:JavaScript的主要用途是与用户互动和操作DOM,这决定了它只能是单线程。否则会带来很复杂的同步问题。比如说:假定JavaScript同时有两个线程,一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准?所以,为了避免复杂性,从一诞生,JavaScript就是单线程,这已经成了这门语言的核心特征,将来也不会改变。
那也就是说,所有任务只能在一个线程上完成,一次只能做一件事。前面的任务没做完,后面的任务只能等着。
Web Worker 的作用,就是为 JavaScript 创造多线程环境,允许主线程创建 Worker 线程,将一些任务分配给后者运行。在主线程运行的同时,Worker 线程在后台运行,两者互不干扰。

基本用法

1.主线程里面调用Worker()构造函数,变可创建worker线程

var worker = new Worker('work.js');  //此处的work.js必须来源于网络

2.然后就可以调用worker.postMessage()向worker线程发送数据

worker.postMessage(param)  

3.接着通过worker.onmessage监听函数,接收子线程发回来的数据

worker.onmessage = function (e) {
//e.data 就是接收到的数据
 ...
}

4.子线程里面通过self.onmessage 来接收主线程发来的数据

self.onmessage = (e) => {
  //e.data 就是接收到的数据
 ...
}

5.子线程里面通过self.postMessage像主线程发送数据

self.postMessage(param)  

6.完成后,关闭线程
因为Worker 线程创建成功,就会始终运行,不会被主线程上打断。这就比较耗费资源,所以一旦使用完毕,就应该关闭子线程。

worker.terminate();//主线程关闭
self.close() //子线程关闭

7.加载其他脚本importScripts

//该方法可以加载多个脚本文件
importScripts('script1.js', 'script2.js');

总体思路:

切片上传

1.通过input [ file ] 选择好文件
2.拿到文件开始计算切片
3.分片读取文件,计算文件hash值
4.根据hash值,后台查看该文件是否上传过,如果上传过,直接提示上传完成,即秒传。如果上传过一部分,则后台返回已经上传的文件切片。
5.在切片的数组中过滤掉已经上传的文件,组装一个request请求池。
6.通过Promise.all方法,等到request请求池完成所有上传后,通知后台合并文件切片。

worker参考文章:https://www.ruanyifeng.com/blog/2018/07/web-worker.html

你可能感兴趣的:(大文件切片上传)