NestJS+Fastify Multipart上传图片至S3损坏问题求助
图片上传S3损坏问题的排查与解决
问题根源
纯文本文件上传正常,但图片变大损坏,本质是二进制数据被错误地以字符串编码(如UTF-8)处理,导致字节流被篡改。文本文件因编码兼容不受影响,但二进制图片的字节结构被破坏后就无法正常解析。
修复方案
方案1:直接用流上传(推荐)
Fastify的MultipartFile本身是可读流,跳过toBuffer()转换,直接把流传给S3,彻底避免编码问题:
修改命令处理逻辑:
// 替换原await image.toBuffer(),直接传入文件流 await this.storageService.uploadFile( image, storageKey, this.configService.get('IMG_BUCKET'), image.mimetype, );
更新uploadFile方法以支持流:
async uploadFile( data: Buffer | NodeJS.ReadableStream, storageKey: string, bucketName: string, type: string, ): Promise<void> { await this.s3Client.send( new PutObjectCommand({ Bucket: bucketName, Key: storageKey, Body: data, ContentType: type, }), ); }
方案2:手动读取Buffer(若必须用Buffer)
如果业务需要先转成Buffer,不要用image.toBuffer()(内部可能默认用字符串编码读取),手动通过流拼接Buffer:
// 替换await image.toBuffer()的代码 const buffer = await new Promise<Buffer>((resolve, reject) => { const chunks: Buffer[] = []; image.on('data', (chunk) => chunks.push(chunk)); image.on('end', () => resolve(Buffer.concat(chunks))); image.on('error', reject); }); await this.storageService.uploadFile( buffer, storageKey, this.configService.get('IMG_BUCKET'), image.mimetype, );
方案3:检查Fastify Multipart配置
确保Fastify的Multipart没有强制字符串编码:
// main.ts中的Fastify配置 async function bootstrap() { const app = await NestFactory.create<NestFastifyApplication>( AppModule, new FastifyAdapter(), ); app.register(require('@fastify/multipart'), { limits: { fileSize: 10 * 1024 * 1024, // 根据业务调整大小限制 }, // 不要添加encoding: 'utf-8'这类配置 }); await app.listen(3000); } bootstrap();
方案4:清理错误的ContentEncoding配置
之前添加的7bit、base64等ContentEncoding参数完全多余——你上传的是原始二进制数据,不是编码后的文本,必须从PutObjectCommand中移除该参数,避免S3错误解码。
验证方式
上传后对比本地文件与S3文件的MD5值:
- 本地执行:
md5sum your-image.jpg - S3控制台查看文件属性的ETag(普通上传下ETag等于文件MD5)
两者一致则说明上传成功。
内容的提问来源于stack exchange,提问作者Paolo Rabbito
相关产品推荐
相关产品推荐

