Next.js项目中调用AWS Lambda Python函数的问题求助
问题分析与解决方案
你的代码存在几个关键问题,导致无法正确调用Lambda函数,同时S3上传环节也有错误:
1. S3上传参数错误
你直接将本地文件路径filepath传给S3的Body参数,但S3 SDK要求Body必须是文件内容(Buffer/Stream),而非文件路径,这会导致S3上传失败。
2. 异步操作未等待完成
s3.upload(params).promise()是异步操作,未使用await会导致S3还未完成上传就调用Lambda,此时S3中不存在目标文件,Lambda自然处理失败。fetch调用Lambda同样是异步操作,未使用await导致无法获取实际返回结果,且extractedText只是一个未resolved的Promise对象。
3. 响应时机错误
直接将未resolved的Promise(results)传给res.send(),不仅不会返回实际的S3上传结果,还会提前结束请求响应,导致后续Lambda调用被中断。
4. 请求方式不匹配
你用method: "post"调用Lambda,但浏览器直接访问URL是GET请求,说明你的API Gateway大概率配置的是GET方法,请求方式不匹配会导致调用失败。
修正后的代码
import fs from 'fs/promises'; import { S3 } from '@aws-sdk/client-s3'; import IncomingForm from 'formidable'; // 禁用Next.js默认的body parser,因为要使用formidable处理表单 export const config = { api: { bodyParser: false, }, }; export default async (req, res) => { try { // 解析表单数据 const { fields, files } = await new Promise((resolve, reject) => { const form = new IncomingForm(); form.parse(req, (err, fields, files) => { if (err) reject(err); else resolve({ fields, files }); }); }); const invoiceFile = files.invoiceFile; if (!invoiceFile) { return res.status(400).send('未上传文件'); } // 读取本地临时文件内容 const fileContent = await fs.readFile(invoiceFile.filepath); // 初始化S3客户端 const s3 = new S3({ accessKeyId: process.env.AWS_ACCESS_KEY, secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY, }); // 配置S3上传参数 const s3Params = { Bucket: process.env.AWS_BUCKET_NAME, Key: invoiceFile.originalFilename, Body: fileContent, ContentType: 'application/pdf', }; // 等待S3上传完成 const s3UploadResult = await s3.upload(s3Params).promise(); console.log('S3上传完成:', s3UploadResult); // 调用Lambda(匹配浏览器访问的GET方法,用encodeURIComponent处理特殊字符) const lambdaResponse = await fetch( `https://xxxxxx.execute-api.us-east-1.amazonaws.com/?message=${encodeURIComponent(invoiceFile.originalFilename)}`, { method: 'GET' } ); if (!lambdaResponse.ok) { throw new Error(`Lambda调用失败: ${lambdaResponse.statusText}`); } // 解析Lambda返回数据(根据实际返回格式调整,比如json/text) const extractedText = await lambdaResponse.json(); console.log('Lambda返回数据:', extractedText); // 返回整合结果给前端,方便存入应用状态 res.status(200).json({ s3UploadResult, extractedText }); } catch (error) { console.error('错误详情:', error); res.status(500).send(`服务器错误: ${error.message}`); } };
额外注意事项
- 确认API Gateway与Lambda的集成配置:如果要使用POST方法,需调整API Gateway资源的集成方式,并将参数放在请求体中传递。
- 增加错误边界处理:比如文件不存在、S3权限不足、Lambda超时等场景的捕获与反馈。
- 文件名包含特殊字符时,必须用
encodeURIComponent转义,避免URL解析错误。
内容的提问来源于stack exchange,提问作者Rich
相关产品推荐
相关产品推荐

