You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript分片上传时如何获取Blob的正确字节大小

分片上传异常的问题排查与修复方案

我帮你看了这段分片上传的代码,几个细节问题很可能就是导致分片异常的原因,咱们一步步捋:

问题1:FormData 没有每次循环重新创建

你现在的代码里,FormData应该是在循环外创建的吧?每次循环都往同一个FormData里append chunkFile,会导致每个请求都带着之前所有的分片数据,后端收到的文件自然是乱的。每次分片请求都要新建一个FormData实例。

问题2:File.slice 的参数逻辑错误

file.slice(start, end-1) 这里的问题很大:

  • File.slice的第二个参数是结束位置(不包含该位置的字节),你写end-1会让每个分片少一个字节,最后合并出来的文件会缺失内容
  • 初始的end设置和更新逻辑也有问题,应该用start + chunkSize作为结束位置,同时要处理最后一个分片不能超过文件总大小的情况

问题3:异步请求的顺序问题

循环里直接批量发送XHR请求,都是异步执行的,后端收到分片的顺序可能和你发送的顺序不一致,最后合并的时候就会把文件拼错。要么改成串行请求(上一个分片上传成功再发下一个),要么给每个分片带上索引标记,让后端能按正确顺序合并。


修正后的代码示例

const chunkSize = 1024 * 1024; // 假设按1MB分片
const fileSize = file.size;
let start = 0;

// 用串行方式上传,保证分片顺序正确
function uploadNextChunk() {
  if (start >= fileSize) return;
  
  const end = Math.min(start + chunkSize, fileSize);
  const blob = file.slice(start, end);
  const formData = new FormData(); // 每次请求新建FormData,避免数据叠加
  
  // 给后端带上分片标识,方便合并
  formData.append('chunkFile', blob, file.name);
  formData.append('chunkIndex', Math.floor(start / chunkSize));
  formData.append('totalChunks', Math.ceil(fileSize / chunkSize));
  
  const xhr = new XMLHttpRequest();
  xhr.addEventListener('load', function (e) {
    console.log(`分片 ${Math.floor(start / chunkSize)} 上传完成`, e);
    start = end;
    uploadNextChunk(); // 触发下一个分片上传
  }, false);
  
  xhr.addEventListener('error', function (e) {
    console.error(`分片 ${Math.floor(start / chunkSize)} 上传失败`, e);
    // 这里可以添加重试逻辑
  }, false);
  
  xhr.open('POST', '../saveUrl');
  xhr.send(formData);
}

// 启动分片上传
uploadNextChunk();

额外提示

  • 后端一定要根据chunkIndex和totalChunks来按顺序合并分片,不能直接按接收顺序合并
  • 可以给每个分片加上文件的唯一标识(比如文件哈希),避免同文件名的文件合并出错
  • 大文件上传建议加上进度条,通过xhr.upload.onprogress来监听单分片或整体上传进度

内容的提问来源于stack exchange,提问作者Mopo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:36:12