AWS Lambda环境下,如何用node-fetch发送文件负载的POST请求?
解决方案:Lambda环境下直接上传JSON报告至Tugboat Logic
核心问题分析
你卡在form.append('file', x, ${reportsArray[i].name}.json);是因为Node环境中,FormData无法直接接收JSON对象作为文件内容,需要先将JSON转换为字符串,再封装成Buffer(Node专属),同时指定正确的MIME类型。此外代码还有几个潜在问题:
- getReports的for循环使用fetch会导致异步并发失控,Lambda环境下可能触发过多请求
- fileReport中的fetch没有处理响应和错误,会导致静默失败
- 手动设置请求头可能覆盖FormData自动生成的
Content-Type(包含boundary),导致服务端解析失败
代码优化方案
完整修改后的代码
getReports.js(重构异步流程,控制并发)
async function getReports(token) { const headers = { method: 'GET', headers: { 'accept': 'application/json', 'Authorization': `Bearer ${token}` }, redirect: 'follow' }; // 批量生成请求Promise,统一处理 const reportTasks = reportsArray.map(async (report, index) => { try { const res = await fetch(report.source, headers); if (!res.ok) throw new Error(`获取报告失败:${res.statusText}`); const payload = await res.json(); return { index, payload }; } catch (err) { console.error(`报告${report.name}获取出错:`, err); throw err; } }); // 等待所有报告获取完成,再逐个上传 const fetchedReports = await Promise.all(reportTasks); for (const item of fetchedReports) { await fileReport(item.index, item.payload); } }
fileReport.js(修复FormData文件上传逻辑)
async function fileReport(i, x) { const form = new FormData(); form.append('collected', getTimestamp()); // 将JSON转为字符串,再封装成Buffer作为文件内容 const jsonContent = JSON.stringify(x); const fileBuffer = Buffer.from(jsonContent); // 正确添加文件:传入Buffer、文件名,指定MIME类型 form.append('file', fileBuffer, { filename: `${reportsArray[i].name}.json`, contentType: 'application/json' }); try { const res = await fetch(`${reportsArray[i].dest}`, { method: 'POST', headers: { 'X-API-KEY': process.env.TUGBOAT_X_API_KEY, 'Authorization': `Basic ${Buffer.from(`${process.env.TUGBOAT_USERNAME}:${process.env.TUGBOAT_PASSWORD}`).toString('base64')}` // 不要手动设置Content-Type,FormData会自动生成带boundary的正确请求头 }, body: form }); if (!res.ok) { const errorDetails = await res.text(); throw new Error(`上传失败:${res.statusText},详情:${errorDetails}`); } console.log(`报告${reportsArray[i].name}上传成功`); return res; } catch (err) { console.error(`报告${reportsArray[i].name}上传出错:`, err); throw err; } }
额外注意事项
- 确保Lambda运行环境为Node.js 18+,原生支持
fetch和FormData;低版本需安装node-fetch和form-data包并适配代码 - 用
Buffer.from(...).toString('base64')替代btoa,避免特殊字符编码问题 - 根据报告数量调整Lambda的内存和超时配置,避免处理超时
内容的提问来源于stack exchange,提问作者David Anderson
相关产品推荐
相关产品推荐

