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

部署AWS Lambda后Node.js+Angular生成的Excel下载后损坏

问题:AWS Lambda部署后Excel文件下载损坏,本地运行正常

使用Node.js结合exceljs库生成Excel文件,通过Angular前端发起请求下载。本地环境下代码运行正常,但部署至AWS Lambda后,下载的Excel文件出现损坏情况,怀疑是API Gateway配置问题,求解决方案。

Node.js 后端代码(原本地版本)

let [row] = await conn.execute(
    "Query",
    []
);

let abc = Object.keys(row[0]);

var workbook = new excel.Workbook();
var worksheet = workbook.addWorksheet('Sheet1');

let clm = [];

abc.forEach(element => {                
    clm.push({ header: element, key: element });
});

worksheet.columns = clm;

worksheet.addRows(row);

var tempFilePath = tempfile('.xlsx');
workbook.xlsx.writeFile(tempFilePath).then(function () {

    res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
    res.setHeader("Content-Disposition", "attachment; filename=temp.xlsx");

    res.sendFile(tempFilePath, function (err) {
        // console.log('---------- error downloading file: ' + err);
    });

});

Angular 前端代码

reports(params: any): Observable<any> {
    return this.http.post(environment.apiUrl + '/reports', JSON.stringify(params), { responseType: 'arraybuffer' })
        .pipe(map((result) => {
            return result;
        }),
            catchError((err) => {
                throw err;
            })
        );
}

this.apicallService
    .reports(json)
    .subscribe(
        (result) => {
            var blob = new Blob([result], { type : "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"});
            var link = document.createElement('a');
            link.href = URL.createObjectURL(blob);
            link.download = filename;
            link.click();
        },
        (err) => {
            this.notifyService.showError(err.message, 'Error');
        }
    );

解决方案

1. 调整Lambda后端代码,适配API Gateway代理集成

本地Express环境的res.sendFile方法在Lambda中不适用,原因是Lambda采用无服务器架构,临时文件存储不可靠,且API Gateway对响应格式有特定要求。修改代码如下:

exports.handler = async (event, context) => {
    // 数据库查询逻辑保持不变
    let [row] = await conn.execute("Query", []);
    let abc = Object.keys(row[0]);
    
    var workbook = new excel.Workbook();
    var worksheet = workbook.addWorksheet('Sheet1');

    let clm = [];
    abc.forEach(element => {                
        clm.push({ header: element, key: element });
    });
    worksheet.columns = clm;
    worksheet.addRows(row);

    // 直接生成文件Buffer,避免写入临时文件
    const fileBuffer = await workbook.xlsx.writeBuffer();

    // 返回符合API Gateway代理集成要求的响应格式
    return {
        statusCode: 200,
        headers: {
            'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
            'Content-Disposition': 'attachment; filename=temp.xlsx',
            // 跨域场景需要添加CORS头,根据实际情况调整
            'Access-Control-Allow-Origin': '*'
        },
        body: fileBuffer.toString('base64'),
        isBase64Encoded: true
    };
};

关键修改点:

  • 使用writeBuffer()直接生成文件二进制Buffer,无需临时文件
  • 响应格式必须包含isBase64Encoded: true,并将Buffer转为base64字符串作为body
  • 正确设置响应头,包括Content-Type和Content-Disposition

2. 配置API Gateway支持二进制媒体类型

API Gateway默认会把非文本响应转成base64,但需要明确指定允许的二进制类型,否则可能导致数据篡改:

  1. 登录AWS控制台,进入API Gateway服务
  2. 选择你的目标API,点击左侧菜单的Settings
  3. 在Binary Media Types区域,添加application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
  4. 点击Save Changes,然后重新部署API(Deploy API -> 选择部署阶段 -> Deploy)

3. 优化Angular请求(可选)

原Angular代码中JSON.stringify(params)可改为直接传递对象,并显式设置Content-Type头,避免潜在的格式问题:

reports(params: any): Observable<any> {
    return this.http.post(environment.apiUrl + '/reports', params, { 
        responseType: 'arraybuffer',
        headers: new HttpHeaders({ 'Content-Type': 'application/json' })
    })
    .pipe(
        map(result => result),
        catchError(err => { throw err; })
    );
}

原因说明

本地环境中Express的sendFile会自动处理二进制文件的传输,但Lambda+API Gateway的组合需要遵循特定的响应规范:API Gateway代理集成要求二进制数据以base64编码返回,并标记isBase64Encoded: true,同时必须在API Gateway中配置对应的Binary Media Types,否则二进制数据会被错误处理,导致下载的Excel文件损坏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 15:50:43