大文件断点续传实现
通过分片上传和断点续传技术实现大文件上传
问题
如何实现大文件的断点续传?上传大文件时会遇到服务器处理能力限制、请求超时、网络波动等问题,导致上传时间长、失败率高,失败后需要重新上传。
解答
分片上传
将文件按照固定大小分割成多个数据块,分别上传后由服务端合并成原始文件。
流程:
- 将文件按规则分割成相同大小的数据块
- 初始化分片上传任务,获取唯一标识
- 按策略(串行或并行)发送各个分片
- 服务端验证数据完整性后合并文件
断点续传
将上传任务划分为多个部分,网络故障时可以从已完成部分继续上传,无需从头开始。
实现方式:
服务器端将文件写为临时文件,记录已上传大小。中断后,下次上传时根据临时文件大小作为偏移量,从该位置继续读取和写入文件。
代码实现
读取文件
const input = document.querySelector('input');
input.addEventListener('change', function() {
const file = this.files[0];
});
生成文件唯一标识
const md5code = md5(file);
分割文件
const chunkSize = 2 * 1024 * 1024; // 2MB
const chunks = Math.ceil(file.size / chunkSize);
for (let i = 0; i < chunks; i++) {
const start = i * chunkSize;
const end = Math.min(start + chunkSize, file.size);
const chunk = file.slice(start, end);
// 上传分片
uploadChunk(chunk, i, md5code);
}
上传分片
function uploadChunk(chunk, index, fileHash) {
const formData = new FormData();
formData.append('chunk', chunk);
formData.append('index', index);
formData.append('hash', fileHash);
fetch('/upload', {
method: 'POST',
body: formData
});
}
服务端合并文件
// 所有分片上传完成后
function mergeChunks(fileHash, totalChunks) {
fetch('/merge', {
method: 'POST',
body: JSON.stringify({ hash: fileHash, total: totalChunks })
});
}
关键点
- 使用文件哈希(如 MD5)作为唯一标识,用于断点续传时识别文件
- 将大文件切割成固定大小的分片(如 2MB),降低单次请求压力
- 服务端保存临时文件和上传进度,支持从中断位置继续上传
- 可采用并行上传提高速度,需控制并发数避免浏览器限制
- 所有分片上传完成后,服务端按顺序合并为完整文件
目录