分片上传(Chunked Upload)
将大文件切分为多个小分片(如每片1-5MB),依次上传至服务器。服务器接收分片后暂存,待所有分片上传完成后合并为完整文件。前端可通过Blob.prototype.slice实现文件分片。
优点:可以避免因网络不稳定或者服务器限制等因素导致的上传失败。
比如,在一个云存储服务中,用户上传一个几GB的视频文件,通过分块,假设文件分成100MB 的小块,即使在上传过程某个小块上传失败,只需要重新上传这个小块即可。
实现分块上传,需要在客户端和服务器端进行协调。客户端需要记录每个块的编号,大小等信息,并且上传时候按照一定的顺序发送这些块。服务端需要接收这些块,并且根据编号等信息去组合成完整的文件。
// 前端分片示例
const chunkSize = 5 * 1024 * 1024; // 5MB
const chunks = Math.ceil(file.size / chunkSize);
for (let i = 0; i < chunks; i++) {
const chunk = file.slice(i * chunkSize, (i + 1) * chunkSize);
uploadChunk(chunk, i);
}
断点续传
记录已上传分片的进度信息(本地存储或服务端返回),上传中断后可从断点继续传输。需配合服务端实现分片校验(如MD5校验)和已上传分片查询接口。
// 恢复上传示例
const uploadedChunks = await checkUploadedChunks(fileId);
for (let i = 0; i < chunks; i++) {
if (!uploadedChunks.includes(i)) {
const chunk = file.slice(i * chunkSize, (i + 1) * chunkSize);
uploadChunk(chunk, i);
}
}
并行上传
通过多个HTTP请求同时上传不同分片,提升传输速度。需注意浏览器并行请求限制(通常为6个),可考虑使用队列控制并发数。可以通过设置合适的Content-length 头部信息,让服务器提前知道文件的大小。文件的不同部分可以上传到不同的节点,然后由分布式文件系统进行整合和存储。提高大文件的上传速度和可靠性。
// 并行上传控制
const MAX_CONCURRENT = 3;
const queue = [];
for (let i = 0; i < chunks; i++) {
queue.push(uploadChunkAsync(i));
if (queue.length >= MAX_CONCURRENT) {
await Promise.race(queue);
}
}
服务端处理
服务端需实现以下接口:
- 分片上传接口:接收分片并临时存储
- 分片合并接口:将所有分片按顺序合并为完整文件
- 分片校验接口:验证分片完整性(如通过MD5)
- 上传状态查询接口:返回已上传分片信息
# Flask分片合并示例
@app.route('/merge', methods=['POST'])
def merge_chunks():
file_id = request.form['file_id']
chunk_dir = os.path.join(UPLOAD_DIR, file_id)
with open(f'{UPLOAD_DIR}/{file_id}.zip', 'wb') as f:
for chunk_num in sorted(os.listdir(chunk_dir)):
f.write(open(os.path.join(chunk_dir, chunk_num), 'rb').read())
进度监控
通过XMLHttpRequest的progress事件或fetch API的TransformStream实现上传进度实时显示。
// 进度监控示例
xhr.upload.addEventListener('progress', (e) => {
const percent = Math.round((e.loaded / e.total) * 100);
progressBar.style.width = `${percent}%`;
});
压缩预处理
前端通过canvas(图片)或pako库(二进制数据)对文件进行压缩,减少传输量。需权衡压缩耗时与体积减少的收益。
WebSocket/P2P传输
对于超大文件(如GB级),可考虑使用WebSocket保持长连接,或WebRTC实现P2P传输绕过HTTP限制。


被折叠的 条评论
为什么被折叠?



