大文件上传的实现方式

分片上传(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())

进度监控

通过XMLHttpRequestprogress事件或fetch APITransformStream实现上传进度实时显示。

// 进度监控示例
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限制。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值