大文件切片上传,断点续传
背景介绍:
1、文件上传超时:原因是前端请求框架认限制最大请求时长,或者是 nginx(或其它代理/网关) 限制了最大请求时长。
2、文件大小超限:原因在于后端对单个请求大小做了限制,一般 nginx 和 server 都会做这个限制。上传耗时久。
3、由于各种网络原因上传失败,且失败之后需要从头开始。
分片原理:
分片上传,就是将所要上传的文件,按照一定的大小,将整个文件分隔成多个数据块(我们称之为Part)来进行分别上传,文件切片和核心是使用 Blob 对象的 slice 方法blob.slice(startByte, endByte),上传完之后再由服务端对所有上传的文件进行汇总整合成原始的文件。
文件妙传,秒传指的是文件在传输之前计算其内容的散列值,也就是 Hash 值,将该值传到后台,如果后台存在 Hash 值一致的文件,认为该文件上传完成。(推荐使用 spark-md5 生成 md5文件,既可以直接返回md5又可以对分片返回md5,对于大体积的文件计算更加稳定)
let baseUrl = 'http://localhost:5000'
let chunkSize = 5 * 1024 * 1024
let fileSize = 0
let file = null
let hasUploaded = 0
let chunks = 0
$("#file").on('change', function () {
file = this.files[0]
fileSize = file.size;
responseChange(file)
})
// 0.响应点击
async function responseChange(file) {
$("#process1").slideDown(200)
// 第一步:开始生成md5
let fileMd5Value = await md5File(file)
// 第二步:校验文件的MD5
let result = await checkFileMD5(file.name, fileMd5Value)
// 如果文件已存在, 就秒传
if (result.file) {
alert('文件已秒传')
return
}
// let exit = false
// 显示文件上传进度
$("#process2").slideDown(200)
// 第三步:检查并上传MD5
await checkAndUploadChunk(fileMd5Value, result.chunkList)
// 第四步: 通知服务器所有分片已上传完成
notifyServer(fileMd5Value)
}
function md5(file, chunkSize) {
let _this = this
return new Promise((resolve, reject) => {
let blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice;
let chunks = Math.ceil(file.size / chunkSize);
let currentChunk = 0;
let spark = new SparkMD5.ArrayBuffer(); //追加数组缓冲区。
let fileReader = new FileReader(); //读取文件
fileReader.onload = function (e) {
spark.append(e.target.result);
currentChunk++;
_this.md5Obj.percent = Math.floor((currentChunk / chunks) * 100);
_this.container.file.MD5Progress = _this.md5Obj.percent
if (_this.onMD5Progress(_this.container.file) === false) return;
if (currentChunk < chunks) {
loadNext();
} else {
_this.md5Obj.md5 = spark.end()