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

Node.js向S3上传大文件时合并分片遇InvalidPart: null错误

解决S3分片合并InvalidPart: null错误及相关疑问

一、InvalidPart错误的核心原因及修复

你的代码存在三个关键问题,直接导致合并时触发InvalidPart错误:

1. 异步上传导致PartNumber重复/顺序混乱

readStream.on("data")会连续触发多个异步的uploadPart请求,但你在uploadPart的回调里才递增partNumber。这会导致多个请求共用同一个partNumber值(比如第一个分片的上传回调还没执行,第二个data事件就已触发,此时partNumber仍为1),最终上传的分片PartNumber重复,S3无法识别合法的分片序列。

修复方式:在触发uploadPart前就确定当前分片的PartNumber,通过闭包保存当前值避免异步干扰:

let partNumber = 1;
let numPartsUploaded = 0;
// 提前通过文件总大小计算总片数,不要用动态变化的bytesRead
const totalParts = Math.ceil(fileSize / partSize);

readStream.on("data", (chunk) => {
  const currentPartNumber = partNumber++; // 先获取当前分片号再递增
  // 确保当前分片的参数使用正确的PartNumber
  const currentPartParams = {
    ...partParams,
    PartNumber: currentPartNumber,
    Body: chunk
  };

  s3.uploadPart(currentPartParams, (err, data) => {
    if (err) {
      console.log("Error upload part", err);
      return;
    }
    console.log(`part ${currentPartNumber} uploaded successfully`);
    parts.push({ ETag: data.ETag, PartNumber: currentPartNumber });
    numPartsUploaded++;

    // 用提前计算的总片数判断是否全部上传完成
    if (numPartsUploaded === totalParts) {
      // S3要求合并时分片必须按PartNumber从小到大排序,显式排序避免异步回调乱序
      parts.sort((a, b) => a.PartNumber - b.PartNumber);
      s3.completeMultipartUpload({
        Bucket: "myBucketName",
        Key: "name",
        UploadId: uploadId,
        MultipartUpload: { Parts: parts },
      }, (err, data) => {
        if (err) {
          console.log("error: ", err);
          return;
        }
        console.log("file uploaded successfully");
      });
    }
  });
});

2. 分片完成判断逻辑错误

你用Math.ceil(readStream.bytesRead/partSize)作为判断条件,但bytesRead会随读取进度动态变化,可能在最后一块数据读取完成时,这个值等于总片数,但此时前面的分片可能还未完成上传(因为uploadPart是异步操作),导致提前调用completeMultipartUpload,此时parts数组还未收集全所有分片的ETag,合并时触发错误。

修复方式:提前获取文件总大小,计算出固定的总片数totalParts,当numPartsUploaded等于totalParts时再触发合并操作。

3. 分片未按要求排序

S3明确要求completeMultipartUpload时,Parts数组必须按PartNumber从小到大排序。即使分片是按顺序上传的,也可能因异步回调的执行顺序导致数组乱序,因此必须显式排序。

二、关于S3分片不可见的疑问

是的,S3控制台不会显示未完成的Multipart Upload分片。这些分片属于未完成的上传会话,只有合并成功后才会生成完整的对象;如果调用abortMultipartUpload,这些分片会被自动清理。你可以通过以下方式查看未完成的上传会话:

  • 在S3控制台目标桶页面,切换到「上传」选项卡查看「正在进行的上传」
  • 使用AWS CLI命令:aws s3api list-multipart-uploads --bucket myBucketName
  • 调用S3的listMultipartUploads API

其他代码小问题

代码里有几处consol.log拼写错误,应改为console.log,否则无法正常输出日志,不利于排查问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 05:10:24