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

JavaScript中blob.slice()返回空Blob问题(大文件分片上传场景)

解决blob.slice()返回空Blob的问题

我来帮你搞定这个大文件分片传输里的空Blob问题,这是分片传输中很常见的坑,咱们从最可能的原因开始排查:

最常见的错误:切片参数搞反了

File.slice()(Blob的子类)的第二个参数是切片的结束位置,不是切片的长度!你的代码里直接传了expectedSize,如果offset已经大于expectedSize,或者expectedSize不是相对于offset的增量,就会出现结束位置小于起始位置的情况,这时候浏览器就会返回空Blob。

修正方案

把结束位置计算为offset + expectedSize,同时确保不超过文件总大小:

const end = Math.min(offset + expectedSize, file.size);
const blobChunk = file.slice(offset, end);

提前终止无效的切片请求

你的代码里判断了offset > file.size,但如果offset等于文件大小,切片同样会返回空Blob。建议改成:

if (offset >= file.size) {
  // 文件已经传输完成,直接返回
  console.log("传输完成,无需继续切片");
  return;
}

另外还要检查expectedSize是否为正数,如果是0或者负数,切片也会返回空Blob:

if (progressModel.ExpectedChunkSize <= 0) {
  throw new Error("分片大小必须是正数");
}

旧浏览器兼容性处理(可选)

虽然现代浏览器都支持标准的slice,但如果你的应用需要兼容旧版Firefox/Chrome,可以做个兼容处理:

const sliceFn = file.slice || (file as any).mozSlice || (file as any).webkitSlice;
const blobChunk = sliceFn.call(file, offset, end);

调试建议

在切片后加个日志,确认参数和切片结果是否正常:

console.log(`切片参数:offset=${offset}, end=${end}, 文件大小=${file.size}`);
console.log(`切片结果大小:${blobChunk.size}`);

如果切片大小还是0,那大概率是progressModel里的Offset或者ExpectedChunkSize值有问题,比如Offset没有正确累加已传输的分片大小。

修正后的完整代码示例

private readonly sendChunk = (file: File, progressModel: ProgressResponseModel): void => {
  const offset = progressModel.Offset;
  const expectedSize = progressModel.ExpectedChunkSize;

  // 校验参数合法性
  if (offset >= file.size) {
    console.log("文件传输已完成");
    return;
  }
  if (offset < 0) {
    throw new Error("偏移量不能为负数");
  }
  if (expectedSize <= 0) {
    throw new Error("分片大小必须为正数");
  }

  // 计算正确的切片结束位置
  const end = Math.min(offset + expectedSize, file.size);
  // 兼容旧浏览器的切片方法
  const sliceFn = file.slice || (file as any).mozSlice || (file as any).webkitSlice;
  const blobChunk = sliceFn.call(file, offset, end);

  // 检查切片是否有效
  if (blobChunk.size === 0) {
    console.error(`切片失败:offset=${offset}, end=${end}, 文件大小=${file.size}`);
    return;
  }

  const xhr = new XMLHttpRequest();
  xhr.onload = (ev: Event) => {
    // 这里写你的加载完成逻辑
  };
  // 后续XHR配置、发送分片的逻辑...
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 04:07:25