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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 18:50:26