大文件切片断点续传总结
起因
产品让我和后端做一个大文件断点续传的Demo
实现
首先在worker线程里面计算文件md5,然后把文件切片,把md5和切片数传给后端,后端返回每个切片的序号以及对应的上传服务器参数,然后把切片上传到文件服务器,每个切片都上传完后发送一个合并文件请求,后端校验切片是否有缺失,如果有缺失则返回错误,如果没有缺失则合并文件。
MD5计算
我使用的库是spark-md5,只有10kb,因为计算大文件hash时间会很长,页面会完全卡死,所以把它放到了worker线程里面。
文件切片
利用File继承自Blob的slice方法,每个切片10Mb。
断点续传
在上传之前会调用一个初始化的请求,把切片数量,md5,文件名称等信息传给后端,后端返回未上传的切片序号,以及对应切片的上传参数,前端只上传后端返回来的这些序号的切片。
遇到的问题
文件服务器tcp数量限制1000个,如果切片超出1000个,同时上传所有的切片,超出1000的请求会报错。这里后端让我做了一个限制,最多同时上传6个切片,我用for循环里面await promise.all的方式。
for (let i = 0; i < Math.ceil(slices.length / 6); i++) {
const reqs = slices.slice(i*6,(i+1)*6).map(()=> this.$axios({url,data,onUploadProgress}))
await Promise.all(reqs)
}
这样写有个弊端,不能最大利用用户的带宽,而且会慢不少,因为每次必须都必须等6个一组的切片上传完才会开始下一组上传,这中间会有一段时间一组里面5个切片都上传完了,只剩1个切片还没上传完。
解决
后来写了一个上传池,保持多个上传请求,一个请求完成,再从等待池里面拉取一个开始上传。