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

Lambda处理程序响应体流返回:Serverless场景S3压缩包下载报错咨询

错误原因

  • 你引入的是fs/promises promise化的fs模块,这个模块不包含createReadStream方法,该方法只存在于基础fs模块中
  • Lambda运行环境的__dirname目录是只读的,不能往这里写文件,必须写到Lambda提供的临时目录/tmp下
  • Lambda的响应对象不能用流的pipe方法直接写入,需要把zip文件转为Buffer后base64编码返回,同时要设置正确的响应头让浏览器识别为下载文件

修改后可运行代码

// 引入需要的依赖
const fs = require('fs');
const fsp = require('fs/promises');
const AdmZip = require('adm-zip');
const AWS = require('aws-sdk');
const s3 = new AWS.S3();
const BUCKET_NAME = '替换为你的S3桶名';

module.exports.handler = async (event) => {
  const response = {
    isBase64Encoded: true, // 二进制文件需要开启base64编码返回
    statusCode: 200,
    headers: {
      'Content-Type': 'application/zip',
      'Content-Disposition': `attachment; filename="download.zip"` // 自定义下载后的文件名
    }
  };

  try {
    const params = {
      Bucket: BUCKET_NAME,
      Key: decodeURIComponent(event.pathParameters.fileKey),
    };
    const data = await s3.getObject(params).promise();
    const zip = new AdmZip(data.Body);
    const entries = zip.getEntries();
    let newZip = new AdmZip();
    for(let entry of entries){
      newZip.addFile(entry.entryName, entry.getCompressedData());
    }
    // 写入Lambda临时目录
    const zipPath = `/tmp/${Date.now()}.zip`;
    newZip.writeZip(zipPath);
    // 读取文件为Buffer后转base64
    const zipBuffer = await fsp.readFile(zipPath);
    response.body = zipBuffer.toString('base64');
    // 可选:删除临时文件避免占用临时空间
    await fsp.unlink(zipPath);
  } catch (error) {
    console.error(error);
    response.headers = {
      'Content-Type': 'application/json'
    };
    response.isBase64Encoded = false;
    response.body = JSON.stringify({ message: 'Failed To Get File', errorMessage: error.message });
    response.statusCode = 500;
  }
  return response;
};

可选优化方案(无需操作本地文件)

AdmZip支持直接生成内存Buffer不需要写入磁盘,可以完全去掉文件读写逻辑,代码更简洁,性能也更高,替换zip处理逻辑即可:

const data = await s3.getObject(params).promise();
const zip = new AdmZip(data.Body);
const entries = zip.getEntries();
let newZip = new AdmZip();
for(let entry of entries){
  newZip.addFile(entry.entryName, entry.getCompressedData());
}
// 直接生成内存buffer转base64,无需读写磁盘
response.body = newZip.toBuffer().toString('base64');

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 04:24:01