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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 11:43:12