S3触发Lambda向API Gateway端点上传文件报错排查求助
代码问题汇总
- 未正确获取S3文件内容:
s3.getObject(params)直接调用返回的是AWS SDK的Request对象,不是文件实际内容,需要调用.promise()搭配await才能拿到包含文件Buffer的返回结果。 multipart/form-data格式错误:原生http模块不支持formData配置项,且你设置的请求头缺少必填的boundary分隔符参数,后端无法解析上传的表单内容。- 写入请求的内容格式错误:直接将对象
post_body传入req.write()会被转为[object Object]字符串,完全不符合表单数据的格式要求。 - 网络请求配置错误:AWS API Gateway默认走HTTPS协议(443端口),你使用
http模块、80端口会直接请求失败。 - 异步逻辑处理缺失:原有代码没有等待S3读取、接口请求完成的逻辑,Lambda很可能在请求执行完成前就被销毁,导致流程中断。
修复方案
推荐使用form-data第三方库自动处理multipart表单的拼接、boundary生成,同时将Lambda handler改为async/await写法简化异步逻辑处理,修改后的代码如下:
提前在本地项目目录执行
npm install form-data axios安装依赖,再打包部署到Lambda。
const AWS = require('aws-sdk'); const axios = require('axios'); const FormData = require('form-data'); const s3 = new AWS.S3({ apiVersion: '2006-03-01' }); exports.handler = async (event) => { // 从S3事件中获取桶和文件key const bucket = event.Records[0].s3.bucket.name; const key = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, ' ')); console.log('Bucket:', bucket, 'Key:', key); try { // 1. 正确获取S3文件内容 const s3File = await s3.getObject({ Bucket: bucket, Key: key }).promise(); console.log('S3文件读取完成,大小:', s3File.ContentLength); // 2. 构造multipart表单数据 const form = new FormData(); // 把S3的文件Buffer放入表单,第三个参数是文件名,可按需修改 form.append('file', s3File.Body, { filename: key.split('/').pop(), contentType: s3File.ContentType }); // 3. 发送POST请求到API Gateway const apiResponse = await axios.post('https://somehostname.amazonaws.com/someValidAPIURL', form, { headers: { // 自动带上带boundary的正确Content-Type ...form.getHeaders() } }); console.log('API请求成功,状态码:', apiResponse.status, '返回内容:', apiResponse.data); return { statusCode: 200, body: '文件上传到API成功' }; } catch (err) { console.error('执行出错:', err); throw new Error(`处理文件${key}失败: ${err.message}`); } };
额外注意事项
- 部署前要将
node_modules和代码一起打包上传到Lambda,否则会报依赖找不到的错误 - 如果你的API Gateway有身份验证(比如API Key、IAM认证),需要在请求头中加上对应的鉴权参数
- 确保Lambda的执行角色有S3的
s3:GetObject权限,以及可以出站访问公网调用API Gateway的权限
内容的提问来源于stack exchange,提问作者Saurabh Tiwari
相关产品推荐
相关产品推荐

