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

使用Node.js的AWS Lambda从Ajax传图至S3时文件损坏求助

解决Ajax上传图片到Lambda+S3后文件损坏的问题

我之前处理过几乎一模一样的场景,图片上传后损坏的核心原因是你在Busboy中处理文件数据时,只保留了最后一段Buffer片段,没有完整拼接所有数据。咱们来一步步修复:

问题根源

在你的Parser函数里,file.on('data')事件会多次触发(大文件会被分片传输),而你直接用result.file = data覆盖之前的内容,最终只保存了最后一小段数据,导致图片文件不完整自然损坏。

修复步骤

1. 修正Parser函数中的文件数据拼接逻辑

把原来的单个Buffer赋值改成数组收集所有片段,最后合并成完整的Buffer:

const parser = (event) => new Promise((resolve, reject) => {
  const busboy = new Busboy({ headers: { 'content-type': getContentType(event) } });
  const result = {};
  // 初始化数组来收集所有文件数据片段
  result.fileChunks = [];

  busboy.on('file', (fieldname, file, filename, encoding, mimetype) => {
    file.on('data', data => {
      // 将每个数据片段push到数组中
      result.fileChunks.push(data);
    });
    file.on('end', () => {
      // 合并所有片段成完整的Buffer
      result.file = Buffer.concat(result.fileChunks);
      result.filename = filename;
      result.contentType = mimetype;
      // 清理临时数组
      delete result.fileChunks;
    });
  });

  busboy.on('field', (fieldname, value) => {
    result[fieldname] = value;
  });
  busboy.on('error', error => reject(error));
  busboy.on('finish', () => {
    event.body = result;
    resolve(event);
  });

  // 确保正确处理base64编码的body
  const bodyBuffer = event.isBase64Encoded ? Buffer.from(event.body, 'base64') : event.body;
  busboy.write(bodyBuffer);
  busboy.end();
});

2. 完善S3上传的参数配置

在uploadPropertyImage函数中显式指定ContentType参数,避免浏览器无法正确识别图片类型(虽然S3会自动检测,但显式设置更稳妥):

const uploadPropertyImage = (buffer, fileName, contentType) => new Promise((resolve, reject) => {
  const bucketName = "BUCKET-NAME";
  var filePath = `${fileName}`;
  const data = {
    Bucket: bucketName,
    Key: filePath,
    Body: buffer,
    ACL: 'public-read',
    ContentType: contentType // 新增:显式设置文件类型
  };
  s3.upload(data, (error, data) => {
    if (!error) {
      resolve(data.Location);
    } else {
      reject(new Error(`上传失败: ${error.message}`));
    }
  });
});

3. 更新Handler中的调用逻辑

记得把文件类型参数也传给上传函数:

parser(event).then(() => {
  var request = event.body;
  if (request.operation == "uploadImage") {
    uploadPropertyImage(request.file, request.filename, request.contentType)
      .then((result) => {
        // 处理成功逻辑
        console.log('图片上传成功:', result);
      }).catch((err) => {
        // 处理错误
        console.error('上传错误:', err);
      });
  }
});

额外检查点

  • 确认API Gateway的集成请求设置中,Content Handling配置为CONVERT_TO_BINARY(如果是使用Lambda代理集成),避免base64编码转换出现问题。
  • 测试时可以打印request.file.length,对比本地文件的大小,确保数据长度一致。

这样修改后,上传的图片就能完整保存到S3了。

内容的提问来源于stack exchange,提问作者Nagesh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 05:18:31