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

React+Serverless+API Gateway解析FormData上传S3文件损坏求助

React + Serverless API Gateway + Lambda 上传文件到S3损坏问题

我尝试通过React前端,借助Serverless框架搭建的API Gateway与Lambda函数,将文件和数据上传至S3存储桶,已困扰多日。

前端代码

前端使用axios构造FormData发送POST请求:

let formData = new FormData();
formData.append('imageFile', selectedImage);
formData.append('itemId', clubIdRef.current.value);
formData.append('itemDescription', itemDescRef.current.value);

axios.post(
            baesURL+"/item/create", formData,
                {headers: {
                    'Content-Type': 'multipart/form-data'
                }}
        
        
        ).then((response) => {
            console.log("response" + response)
            console.log("response.data" + response.data)
        })

虽然将字符串属性加入FormData感觉不太合理,但这是我找到的同时传输数据和图片的唯一方式。

后端解析情况

后端使用lambda-multipart-parser解析数据:

const createItem = async (event) => {

  const result = await multipartParser.parse(event);
  const imageFile = result.imageFile;
  const itemDescription = result.itemDescription;

解析结果打印为:

{
  files: [],
  imageFile: '[object File]',
  itemId: '12',
  itemDescription: "Description"
}

S3上传问题

我能将imageFile存入S3并生成URL,再结合URL、id和description创建Item对象存入DynamoDB,流程看似正常,但打开S3 URL时文件损坏,仅显示灰色方框。S3上传代码如下:

const AWS = require("aws-sdk");
const s3 = new AWS.S3();
const params = {
      Bucket: BUCKET_NAME,
      Key: `images/${directoryPath}/${id}.png`,
      Body: imageFile,
      ContentType: "image/png",
      ACL : "public-read"
    }
    
uploadResult = await s3.putObject(params).promise();

已尝试的无效方法

  • 尝试修改API Gateway的BinaryMediaType,但找不到对应设置;
  • 使用aws-lambda-multipart-parser,仍无法添加multipart/form-data二进制媒体类型并正确解析完整FormData。

我知道可以通过React直接调用aws-sdk获取预签名URL上传图片,再将URL通过POST请求发送至API Gateway解析event.body,但希望避免多请求,在后端完成全部处理。


解决方案

核心问题

解析后的imageFile是字符串[object File],说明multipart解析器未正确处理二进制文件,仅将文件对象转为字符串,导致S3存储的是无效内容。

步骤1:配置API Gateway支持二进制传输

  1. 进入API Gateway控制台,选择你的API;
  2. 切换到Settings(设置)选项卡;
  3. 在Binary Media Types中添加multipart/form-data;
  4. 重新部署API(必须部署才会生效)。

步骤2:更换并正确使用解析库

使用aws-lambda-multipart-parser(支持二进制解析),修改Lambda代码:

const multipartParser = require('aws-lambda-multipart-parser');

const createItem = async (event) => {
  // 解析带二进制的FormData,第二个参数true表示处理base64编码的body
  const result = await multipartParser.parse(event, true);
  
  // 从files数组中获取上传的文件
  const imageFile = result.files.find(file => file.fieldname === 'imageFile');
  const itemId = result.itemId;
  const itemDescription = result.itemDescription;

  // 上传S3时使用文件的二进制内容
  const AWS = require("aws-sdk");
  const s3 = new AWS.S3();
  const params = {
    Bucket: BUCKET_NAME,
    Key: `images/${directoryPath}/${itemId}.png`,
    Body: imageFile.content, // 取文件的二进制Buffer
    ContentType: imageFile.contentType, // 用解析到的真实文件类型,不要硬编码
    ACL: "public-read"
  };
  
  const uploadResult = await s3.putObject(params).promise();
  
  // 后续存入DynamoDB的逻辑...
};

步骤3:前端代码优化

去掉手动设置的Content-Type,axios会自动生成包含boundary的正确头:

axios.post(
  baesURL+"/item/create", formData
).then((response) => {
  console.log("response", response);
  console.log("response.data", response.data);
})

验证

  1. 重新部署API Gateway;
  2. 测试请求后,检查Lambda中result.files是否包含完整的文件对象(含content、contentType属性);
  3. 查看S3文件大小是否与原文件一致,一致则上传成功。

内容的提问来源于stack exchange,提问作者ph-quiett

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 13:55:20