js断点续传

我们在做上传文件的时候,如果需要上传一个百兆的大文件,上传时间就会比较慢(要输出更多的报文,丢失中重传的概率也更大),用户不能刷新页面,只能耐心等待请求完成。

所以,我们可以将其切割成适当的小文件,提交给后台,再由后台合并成大文件

这样做的好处是:

  1. 化整为零,可以防止文件上传中段而导致整个文件都需要重新上传的问题,
  2. 分成小文件,可以利用ajax的多线程,同时提交多个小文件,从而提升上传速度。js断点续传_第1张图片

二、断点续传实现

1.接口文档

要 实现断点续传,后台必须实现下面接口:

(1)文件上传接口

接口说明此接口用于上传文件切片,file参数是文件切片的内容。后台在保存的时候,可以将同一个文件的切片保存到一个文件夹下,所以原文件名称是可能需求的参数。为了保证切片的唯一性,id作为文件签名是必须的。由于并发的提交,为了保证文件切片的顺序,所以要加上index。

注意:后台在记录文件签名的时候,是可以采用多种方法记录的。但是一定要考虑文件的并发提交对数据存储和查询的影响。

请求方式post,入参:

{
  "file":"Blob",   // 文件切片
  "filename":"1.text",    //文件名称
  "index":2,    // 切片序号
  "id":"cdee9e473d48764864028e38936bb62d"  // 文件唯一识别,这里采用md5生成
}

返回值:

{
  "code":!
}

(2)文件合并接口

接口说明合并接口即把切片文件合并,在合并文件的时候,注意考虑切片的序列号。

请求方法:post

入参

{
  "filename":"1.text"   //文件名称
}

返回值:

{
  "code":1   // 返回码 1成功 0失败
}

(3)查询文件接口:

接口说明查询文件是否存在,如存在,前端不要发起ajax上传。

请求方法:post

入参:

{
  "id":"cdee9e473d48764864028e38936bb62d",  //文件姓名
  "filename":"1.text",                      //文件名称
  "index":2                                 //切片序号
}

返回值:

{
 "code":1,           // 返回码 1成功 0失败
 "isExist":1         // 是否存在 1存在 0不存在
}

2.fileupload.js原理

(1).文件切割

js的Blob对象提供了slice方法,而File对象继承Blob,则File文件就可以切割为小分片提交给后台。

(2)文件签名

小分片的提交,就学英语判断小分片是否存在,我们可以在文件分片的时候把文件签名带上,通过比较文件签名是否存在,来判断文件是否已经上传。

补充:md5可以使用spark-md5.js来生成

(3)http的并发
普通的文件上传,只会发起一个http连接。但主流浏览器http最大并发连接数,一般都达到了6个。显然资源的利用率不够,把文件切割成分片,则可以并发的提交文件,以达到浏览器资源的充分利用。


3. fileupload.js使用

fileupload.js对接了上面接口。

(1)实例化Fileupload
fileupload.js构造函数如下:

var fileupload = new Fileupload({
  upload: './php/upload.php',
  query: './php/query.php',
  merge: './php/merge.php',
  cache: false,
  slicesize: 4 * 1024,
  thread: 4,
  filesign: SparkMD5.ArrayBuffer.hash
});

参数含义:

参数 是否必须 含义 缺省
upload 上传接口url -
query 查询接口url -
merge 合并接口url -
cache 是否使用本地缓存 true
slicesize 切片大小 4M
thread 线程数 3
filesign 文件签名算法 例如md5

说明:

  1. cache 设置为true,则fileupload.js会将文件签名记录到浏览器的localStorage里面,则查询后台之前,会先检查本地记录,如果本地记录存在,则不会上传,本地记录不存在,则调用后台查询。
  2. slicesize 此处为切片大小的设置,理论上讲,切片过大则不能实现断点的功能,而切片过小,则计算和交互又太过于频繁而降低性能。那么一定存在一个切片大小的最优解。
  3. thread 线程数,此时的线程指的是浏览器ajax线程,在实际经验中,chrome并发表现优于ie,这里可以根据浏览器类型,自行设置。
  4. filesign 文件签名算法,任何文件签名都有发生碰撞的可能,fileupload.js做出任何实现都是考虑不完善的。同时,hash算法的抗碰撞性和性能是冲突的。所以根据产品特性,做出合理的文件签名算法才是合理的。

(2)上传文件
fileupload.js上传文件操作如下:

var files = document.getElementById("file");
var file = files.files
fileupload.addFile(file);
fileupload.upload();

addFile接口可以使多个文件,upload方法被调用则开始启动上传。


(3)事件监听
fileupload.js事件监听如下:

fileupload.on({
  success: function() {
    alert('上传完成');
  },
  complete: function(filename) {
    alert(filename + '上传完成');
  },
  query: function(data) {
    console.log(data);
  },
  merge: function(data) {
    console.log(data);
  },
  upload: function(data) {
    console.log(data);
  },
  progress: function(progress) {
    progress = 100 * progress;
    document.getElementById("progess").value = progress.toFixed(2);
  }
});
事件 含义
success 所有上传文件成功
complete 单个文件上传成功
query 查询接口返回事件
merge 合并接口返回事件
upload 上传接口返回事件
progress 进度

fileupload.js也可以下面监听事件:

fileupload.on('progress', function (progress) {
  console.log(progress);
});
  •  

(3)暂停
fileupload.js切片操作都是异步实现。其暂停后会持续地推迟下一个分片的动作以阻止上传的行为,直至暂停取消。
理论上暂停操作会轻微的影响性能,但不会和主线程竞争资源。

fileupload.setPause(isPause);

isPause:
true为暂停,
false为继续


三、 fileupload.js源码

demo后台由php完成

github地址:
https://github.com/fwx426328/resumebreakpoint

代码量:400行

你可能感兴趣的:(js断点续传)