我们在做上传文件的时候,如果需要上传一个百兆的大文件,上传时间就会比较慢(要输出更多的报文,丢失中重传的概率也更大),用户不能刷新页面,只能耐心等待请求完成。
所以,我们可以将其切割成适当的小文件,提交给后台,再由后台合并成大文件
这样做的好处是:
要 实现断点续传,后台必须实现下面接口:
(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不存在
}
(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 |
说明:
(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为继续
demo后台由php完成
github地址:
https://github.com/fwx426328/resumebreakpoint
代码量:400行