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

本地正常的S3上传Lambda部署后失效问题求助

问题诊断与解决方案

一、文件损坏/无法查看的修复方案

问题核心是Lambda处理API Gateway请求时,二进制数据编码/解码逻辑错误,导致上传到S3的文件并非原始二进制内容。

代码层面修复

调整Node.js代码,正确处理二进制请求体并保留文件元数据:

const AWS = require('aws-sdk');
const s3 = new AWS.S3();

exports.handler = async (event) => {
  // 根据API Gateway标记判断是否需要Base64解码
  const fileContent = Buffer.from(event.body, event.isBase64Encoded ? 'base64' : 'utf8');
  const uploadParams = {
    Bucket: 'your-target-bucket',
    Key: event.queryStringParameters?.fileName || 'default-file-name',
    Body: fileContent,
    // 保留原始请求的Content-Type,确保S3文件元数据正确
    ContentType: event.headers['content-type'] || 'application/octet-stream'
  };

  try {
    await s3.putObject(uploadParams).promise();
    return {
      statusCode: 200,
      body: JSON.stringify({ success: true, message: '文件上传成功' })
    };
  } catch (err) {
    return {
      statusCode: 500,
      body: JSON.stringify({ success: false, error: err.message })
    };
  }
};

API Gateway配置修复

  • 开启二进制媒体类型:进入API Gateway控制台,找到对应API的「设置」页面,添加需要支持的二进制类型(如image/*、application/pdf或通配符*/*)。
  • 集成请求配置:将集成请求的「内容处理」设置为「通过(Passthrough)」,避免API Gateway自动修改二进制数据。

二、大文件上传报错的修复方案

问题根源是API Gateway默认最大请求 payload 为10MB,Lambda同步调用最大payload为6MB,超过限制会触发报错。

方案1:调整基础配置(支持最大10MB文件)

在Serverless框架配置文件中增加API Gateway的payload限制:

service: s3-upload-service
provider:
  name: aws
  runtime: nodejs18.x
  apiGateway:
    maximumPayloadSize: 10485760 # 10MB,单位为字节
functions:
  uploadToS3:
    handler: handler.uploadToS3
    events:
      - http:
          path: upload
          method: post
          cors: true
          request:
            contentHandling: CONVERT_TO_BINARY # 开启二进制转换支持

注意:此方案仅支持最大10MB的文件,超过10MB需用方案2。

方案2:预签名URL上传(推荐大文件场景)

绕过API Gateway和Lambda的payload限制,让前端直接通过S3预签名URL上传文件:

Lambda生成预签名URL的代码

const AWS = require('aws-sdk');
const s3 = new AWS.S3();

exports.getPresignedUrl = async (event) => {
  const { fileName, contentType } = JSON.parse(event.body);
  const params = {
    Bucket: 'your-target-bucket',
    Key: fileName,
    ContentType: contentType,
    Expires: 3600 // URL有效期1小时
  };

  try {
    const presignedUrl = s3.getSignedUrl('putObject', params);
    return {
      statusCode: 200,
      body: JSON.stringify({ presignedUrl })
    };
  } catch (err) {
    return {
      statusCode: 500,
      body: JSON.stringify({ error: err.message })
    };
  }
};

Serverless配置新增函数

functions:
  getPresignedUrl:
    handler: handler.getPresignedUrl
    events:
      - http:
          path: get-presigned-url
          method: post
          cors: true

前端上传逻辑示例

async function uploadFile(file) {
  // 先请求预签名URL
  const urlResp = await fetch('/get-presigned-url', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ fileName: file.name, contentType: file.type })
  });
  const { presignedUrl } = await urlResp.json();

  // 直接上传到S3
  await fetch(presignedUrl, {
    method: 'PUT',
    body: file,
    headers: { 'Content-Type': file.type }
  });
}

三、额外检查项

  • 确认Lambda的IAM角色拥有s3:PutObject权限,且权限范围包含目标S3桶。
  • 若使用预签名URL方案,需配置S3桶的CORS规则,允许前端PUT请求:
<CORSConfiguration>
  <CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedMethod>PUT</AllowedMethod>
    <AllowedHeader>*</AllowedHeader>
  </CORSRule>
</CORSConfiguration>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 09:42:37