大文件上传,会遇到请求超时,网络波动,服务器处理数据的能力,这些都会影响我们的用户体验。
文件大,上传的事件变长,高频次上传文件失败,失败后又需要重新上传。
有两种方案可以解决这些问题:分片上传和断点续传
分片上传
分片上传就是把要上传的文件,按照一定的大小,将整个文件分割成多个数据块来分片上传。
上传完成后,再由服务器对所有上传的文件进行汇总合成原始文件。
流程如下:
- 把上传的文件按照一定的分割规则,分割成相同大小的数据块
- 初始化一个上传任务,返回本次分片上传的唯一标识
- 按照一定的策略【串行或者并行】发送各个分片数据块
- 发送完成后,服务端判断数据上传是否完整,如果完整,就进行数据块合成得到原始文件
断点续传
断点续传是在上传或者下载的时候,把上传或者下载任务人为划分为几个部分。
每一个部分采用一个线程进行上传或者下载,如果碰到网络故障,可以从已经上传或者下载的部分开始继续上传或者下载未完成的部分。没有必要从头开始下载或者上传。这样用户节省时间,提高速度
一般实现的方式有两种:
- 服务器端返回,告知从哪里开始
- 浏览器端自行处理
上传过程中,在服务端把文件写为临时文件,等全部上传完成后,把临时文件重命名为正式文件
如果上传途中中断了,下次上传的时候,根据当前临时文件的大小,作为在客户端读取文件的偏移量,从此位置继续读取文件数据,上传到服务器从此偏移量继续写入文件。
实现的代码:
const input = document.querySelector('input');
input.addEventListener('change', function() {
var file = this.files[0];
});
使用md5实现文件的唯一性:
const md5code = md5(file);
对文件进行分割:
var reader = new FileReader();
reader.readAsArrayBuffer(file);
reader.addEventListener("load", function(e) {
// 每10M切割一段
var slice = e.target.result.slice(0, 10*1024*1024);
});
上传:
const formdata = new FormData();
formdata.append('0', slice);
//
formdata.append('filename', file.filename);
var xhr = new XMLHttpRequest();
xhr.addEventListener('load', function () {
//xhr.responseText
});
xhr.open('POST', '');
xhr.send(formdata);
xhr.addEventListener('progress', updateProgress);
xhr.upload.addEventListener('progress', updateProgress);
function updateProgress(event) {
if (event.lengthComputable) {
//
}
}
这个仅仅是一种思路,在实际开发中,需要具体分析。