使用@fastify/multipart流式传文件到AWS S3报未实现错误
问题分析与解决方案
错误原因
你遇到的NotImplemented错误核心原因在于:
@fastify/multipart返回的文件流没有提供明确的Content-Length值,AWS SDK在处理这种流时会自动添加Transfer-Encoding: chunked请求头,但S3的PutObject接口不支持分块编码上传,因此触发该错误。
而原生fs.createReadStream返回的流带有文件大小元数据,AWS SDK能自动获取并设置Content-Length请求头,符合S3的要求,所以可以正常上传。
解决方案
以下是两种可行的修复方案:
方案1:使用AWS SDK的Upload类(推荐)
@aws-sdk/lib-storage包中的Upload类专门用于处理流式上传,会自动处理无明确长度的流,将其拆分为分块上传到S3,无需手动处理Content-Length。
首先安装依赖:
npm install @aws-sdk/lib-storage
修改后的代码:
import { S3Client } from '@aws-sdk/client-s3'; import { Upload } from '@aws-sdk/lib-storage'; export const uploadImage = async (req, res) => { // 获取上传的文件流 const data = await req.file(); // 初始化S3客户端 const s3Client = new S3Client({ region: 'your-region', credentials: { accessKeyId: 'your-access-key', secretAccessKey: 'your-secret-key' } }); // 创建上传实例 const upload = new Upload({ client: s3Client, params: { Bucket: 'your-bucket-name', Key: data.filename, // 使用上传文件的原始文件名,避免固定命名覆盖 Body: data.file } }); // 执行上传 await upload.done(); return res.code(200).send({ status: 'success' }); };
方案2:手动设置Content-Length
如果坚持使用PutObjectCommand,可以从@fastify/multipart返回的文件对象中获取文件大小,手动设置Content-Length参数:
import { PutObjectCommand, S3Client } from '@aws-sdk/client-s3'; export const uploadImage = async (req, res) => { const data = await req.file(); const s3Client = new S3Client({ region: 'your-region', credentials: { accessKeyId: 'your-access-key', secretAccessKey: 'your-secret-key' } }); const command = new PutObjectCommand({ Bucket: 'your-bucket-name', Key: data.filename, Body: data.file, // 从multipart文件对象中获取文件大小 ContentLength: data.size }); await s3Client.send(command); return res.code(200).send({ status: 'success' }); };
注意:确保
data.size存在,@fastify/multipart解析后的文件对象通常会包含该属性,表示文件的字节大小。
内容的提问来源于stack exchange,提问作者AndroidUserOnAppleDevice
相关产品推荐
相关产品推荐

