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

AWS Lambda处理multipart/form-data时图片上传S3损坏求助

解决方案

核心问题分析

  • 你使用的Buffer.from(..., 'binary')编码参数错误:API Gateway会将二进制请求体编码为base64,用'binary'解析会导致字节丢失或乱码,直接破坏图片数据。
  • 用字符串正则搜索定位内容起始位置的逻辑有问题:二进制数据转字符串时会丢失原始字节结构,导致切片位置偏移,最终截取的内容不完整。
  • 其他npm包返回空数组,大概率是因为你没把event.body从base64解码为原始buffer——这类工具需要直接处理二进制multipart数据,而非base64字符串。

修正步骤

1. 先正确处理API Gateway的输入

API Gateway默认将二进制请求体编码为base64,第一步必须把event.body解码为原始buffer:

const rawBody = Buffer.from(event.body, 'base64');

2. 替换损坏的Buffer处理代码

放弃字符串操作,直接用buffer定位内容区间,修正后的核心逻辑(替代原代码中那行Buffer.from):

// 定位headers和内容的分隔符(\r\n\r\n)位置
const headerContentSeparator = part.indexOf('\r\n\r\n');
// 内容从分隔符后4个字节开始,到倒数4个字节结束(移除末尾的分隔符后缀)
const contentBuffer = part.slice(headerContentSeparator + 4, part.length - 4);

注:这里的part需要是分割后的multipart二进制buffer,若原代码中part是字符串,需先转回buffer再处理。

3. 完整修正后的解析示例

基于原有的解析逻辑重写,避免字符串操作破坏二进制数据:

function parseMultipart(event) {
  const boundary = extractBoundary(event.headers['Content-Type']);
  const rawBody = Buffer.from(event.body, 'base64');
  const parts = splitMultipartBuffer(rawBody, boundary);

  return parts.map(part => {
    // 解析part的headers
    const headerEnd = part.indexOf('\r\n\r\n');
    const headerStr = part.slice(0, headerEnd).toString('utf8');
    const headers = parseHeaders(headerStr);

    // 获取原始内容buffer
    const content = part.slice(headerEnd + 4, part.length - 4);

    return {
      filename: headers['Content-Disposition']?.match(/filename="?([^"]+)"?/)?.[1],
      contentType: headers['Content-Type'],
      content: content
    };
  });
}

// 辅助函数:按分隔符分割multipart buffer
function splitMultipartBuffer(buffer, boundary) {
  const boundaryBuffer = Buffer.from(`--${boundary}`);
  const parts = [];
  let startPos = 0;

  while (startPos < buffer.length) {
    const nextBoundaryIndex = buffer.indexOf(boundaryBuffer, startPos);
    if (nextBoundaryIndex === -1) break;
    if (nextBoundaryIndex > startPos) {
      parts.push(buffer.slice(startPos, nextBoundaryIndex));
    }
    startPos = nextBoundaryIndex + boundaryBuffer.length;
  }

  return parts.filter(part => part.length > 0);
}

// 辅助函数:解析headers字符串
function parseHeaders(headerStr) {
  return headerStr.split('\r\n').reduce((acc, line) => {
    const [key, value] = line.split(': ');
    if (key) acc[key] = value;
    return acc;
  }, {});
}

// 提取boundary的辅助函数
function extractBoundary(contentType) {
  return contentType.split('boundary=')[1];
}

4. 上传S3的注意事项

上传时直接使用解析得到的content buffer,不要额外编码,同时设置正确的Content-Type:

const s3Params = {
  Bucket: '你的存储桶名称',
  Key: '图片存储路径/xxx.jpg',
  Body: part.content,
  ContentType: part.contentType
};

await s3.putObject(s3Params).promise();

其他npm包的正确用法

如果想用parse-multipart或parse-multipart-data,必须传入解码后的原始buffer:

const rawBody = Buffer.from(event.body, 'base64');
const boundary = extractBoundary(event.headers['Content-Type']);
const parts = parseMultipart(rawBody, boundary); // 传buffer而非event.body

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 07:11:00