文件分片上传,断点续传
为什么文件要分片上传?
当单文件过大时,因为传输和后端处理文件时间过长都会导致时间过长,如果代理服务器没有在期望时间内获得后端处理程序返回内容,就会向前端抛出timeout错误。所以文件过大,需要对文件进行拆分,分成体积更小的内容进行上传,保证每次后端都能在规定时间内处理完成并告知代理服务器,由上传一次变成上传多次。
分片
分片作为第一个步骤,主要通过File.slice方法来完成分片。
同时设定每个碎片容量的最大值。
示例代码: 分片
/* file - 文件对象 */
/* chunkSize - 碎片容量 */
const totalChunk = Math.ceil(file.size / chunkSize);
const fileChunkList = new Array(totalChunk);
for (let i = 0; i < totalChunk; i += 1) {
const fileChunk = new File(
[file.slice(i * chunkSize, (i + 1) * chunkSize)],
`${i}${file.name}`,
{
type: file.type,
},
);
fileChunkList[i] = {
total: totalChunk,
current: i + 1,
chunkSize:
fileChunk,
};
}
上传
完成文件分片之后,就要对每个碎片进行上传。fileChunkList是上面得到的碎片列表,现在要把它的每个碎片上传给后端,咋弄?显然,不能直接同时对所有碎片进行上传,不然后端面对高并发也可能超时。所以需要对碎片上传流程进行控制。控制上传流程有很多方式,提供一种方式。
/* sliceUpload - 上传函数 */
const sliceUpload = async ( fileChunk, next ) => {
/* fileChunk - 文件碎片 */
/* next - 调度函数,执行下一个碎片上传 */
/* upload - 碎片上传ajax */
const ok = await upload(fileChunk)
if(!ok) return /* 错误处理 */
/* 下一个碎片上传 */
next()
}
/* fileChunkList - 文件碎片列表 */
/* fileChunkUploadFnList - 文件碎片上传函数列表 */
const fileChunkUploadFnList = fileChunkList.map((i, index, arr) => {
/* next函数 调度下个分片的上传 */
const next = async () => {
if (index + 1 < arr.length) {
fileChunkUploadFnList[index + 1]?.();
}
};
return async () => {
try {
await sliceUpload?.(i, next);
} catch {
console.log('上传失败');
}
};
});
断点续传
在每次碎片成功将序列号存进localStorage,文件的md5作为key值。再次上传后通过获取上次成功了的序列号,对碎片列表进行过滤,把已经上传成功碎片排除,再进行upload。就不写样例代码了...
总结
1.通过File.slice 对文件进行分片
2.对文件碎片上传进行流程控制
3.结合前端存储做断点续传
有错误的地方,麻烦指正一下,谢谢。技术分享完毕。