如何最小化修改代码适配未知长度Stream的S3上传?
问题:S3上传未知长度Stream报错,如何最小改动适配?
我现有代码在普通文件上传时运行正常,但使用未知长度的Stream上传时触发以下报错:
Are you using a Stream of unknown length as the Body of a PutObject request? Consider using Upload instead from @aws-sdk/lib-storage.
尝试过多种方式使用lib-storage但未能成功实现需求,想知道对现有代码做最小改动就能支持未知长度Stream的方法。
现有代码:
import { S3Client, HeadObjectCommand, PutObjectCommand, GetObjectCommand } from '@aws-sdk/client-s3' // ... const s3 = new S3Client({ region: 'ap-southeast-2', defaultProvider }) // ... class Files extends AuditMixin { async _uploadToAmazon (path, body) { const params = { Bucket: vars.config.amazonBucket, Key: path } let found = 0 try { await s3.send(new HeadObjectCommand(params)) found = 1 } catch (e) { if (e.name === 'NotFound') found = 0 } if (found) { console.log('****************Skipped! ', path) return { key: path } } else { console.log('I would upload', path) try { const response = await s3.send(new PutObjectCommand({ ...params, Body: body })) return response } catch (error) { console.error('Error uploading to Amazon S3:', error) throw error } } } }
目前有一个可行但体验很差的临时方案:
import cs from 'convert-stream' // ... if (typeof body.pipe === 'function') { body = await cs.toBuffer(body) } const response = await s3.send(new PutObjectCommand({ ...params, Body: body }))
解决方案:用@aws-sdk/lib-storage的Upload替换PutObjectCommand
只需两步最小改动,无需转换整个Stream为Buffer:
- 导入
Upload类:
// 在原有导入基础上添加这行 import { Upload } from "@aws-sdk/lib-storage";
- 修改
_uploadToAmazon方法中上传逻辑的代码块,替换原有的PutObjectCommand调用:
// 替换else分支里的try代码块 try { console.log('I would upload', path) // 用Upload替代PutObjectCommand const upload = new Upload({ client: s3, params: { ...params, Body: body } }); const response = await upload.done(); return response; } catch (error) { console.error('Error uploading to Amazon S3:', error) throw error }
说明
- 原有文件存在检查逻辑完全保留,无需修改
Upload会自动处理未知长度的Stream,采用分块上传机制,避免了把整个Stream加载到内存的问题- 接口返回值与原
PutObjectCommand的返回兼容,无需调整后续逻辑
内容的提问来源于stack exchange,提问作者Merc
相关产品推荐
相关产品推荐

