在AWS SDK v3中如何通过UploadId跟踪S3分片上传进度?
AWS SDK v3 中 UploadPart 跟踪分片上传进度的等效实现
在AWS SDK v3中,UploadPartCommand本身没有提供像v2那样直接的httpUploadProgress事件监听,需要通过包装Body流的方式来实现分片上传进度的跟踪,同时可以关联对应的UploadId和PartNumber。
实现步骤与代码示例
- 首先确保安装了必要的依赖:
npm install @aws-sdk/client-s3 @aws-sdk/util-stream-node
- 自定义进度跟踪流,并包装分片上传的Body:
const { S3Client, UploadPartCommand } = require("@aws-sdk/client-s3"); const { createReadStream } = require("@aws-sdk/util-stream-node"); const { Transform } = require("stream"); // 自定义Transform流,用于跟踪上传进度 class ProgressTracker extends Transform { constructor(options = {}) { super(options); this.totalBytes = options.totalBytes || 0; this.uploadedBytes = 0; this.onProgress = options.onProgress || (() => {}); } _transform(chunk, encoding, callback) { this.uploadedBytes += chunk.length; // 触发进度回调,携带分片编号和上传ID this.onProgress({ loaded: this.uploadedBytes, total: this.totalBytes, partNumber: this.partNumber, uploadId: this.uploadId }); this.push(chunk); callback(); } } // 初始化S3客户端 const s3Client = new S3Client({ // 你的AWS配置,比如region、credentials等 }); // 封装带进度跟踪的分片上传方法 async function uploadPartWithProgress(uploadParams) { // 创建进度跟踪器 const progressTracker = new ProgressTracker({ totalBytes: uploadParams.ContentLength, onProgress: (evt) => { console.log(`分片 ${evt.partNumber} (UploadId: ${evt.uploadId}) 上传进度: ${((evt.loaded / evt.total) * 100).toFixed(2)}%`); console.log(`已上传: ${evt.loaded} / ${evt.total} 字节`); } }); // 绑定当前分片的标识信息 progressTracker.partNumber = uploadParams.PartNumber; progressTracker.uploadId = uploadParams.UploadId; // 将原始Body转换为带进度跟踪的流 const trackedBody = typeof uploadParams.Body === 'string' ? createReadStream(uploadParams.Body).pipe(progressTracker) : uploadParams.Body.pipe(progressTracker); // 替换参数中的Body为跟踪流 const paramsWithProgress = { ...uploadParams, Body: trackedBody }; // 执行分片上传并返回结果 return await s3Client.send(new UploadPartCommand(paramsWithProgress)); } // 使用示例 (async () => { try { const partInfo = await uploadPartWithProgress({ Bucket: "BucketName", Key: "目标对象Key", UploadId: "你的多部分上传ID", PartNumber: 1, // 当前分片编号(1-10000) ContentLength: 1048576, // 分片大小(示例为1MB) Body: "/本地分片文件路径" // 或直接传入Readable流 }); console.log("分片上传完成,ETag:", partInfo.ETag); } catch (err) { console.error("分片上传失败:", err); } })();
补充说明
- 如果使用全局中间件监听进度(如
NodeHttpHandler的progress配置),无法直接关联到特定的UploadId和PartNumber,因此在多分片并行上传场景下,自定义流的方式更精准。 - 上述代码中的
ProgressTracker可以根据需求扩展,比如添加速度计算、状态标记等功能。
内容的提问来源于stack exchange,提问作者xavier392
相关产品推荐
相关产品推荐

