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

Node.js下如何在AWS Lambda中实现流式文件上传

Lambda 流式处理 Multipart 大文件上传方案(替代 Express+Multer)

核心思路

Lambda 的 streamifyResponse 包装器支持直接处理原生请求流与响应流,无需将 API Gateway/ALB 的 event 转换成模拟的 Express req 对象。我们可以直接获取原始请求流,配合 Busboy 解析 multipart 数据,全程流式处理,避免将10MB-1GB的大文件加载到内存中。

具体实现步骤

1. 安装依赖

npm install busboy @aws-sdk/client-s3

2. 流式处理函数代码

import { streamifyResponse } from 'aws-lambda';
import Busboy from 'busboy';
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';

// 初始化S3客户端
const s3Client = new S3Client({ region: 'your-region-id' });

export const handler = streamifyResponse(async (event, responseStream, context) => {
  // 转换请求头为小写(Busboy要求)
  const lowerCaseHeaders = Object.fromEntries(
    Object.entries(event.headers || {}).map(([key, val]) => [key.toLowerCase(), val])
  );

  // 初始化Busboy,设置文件大小上限为1GB
  const bb = Busboy({
    headers: lowerCaseHeaders,
    limits: { fileSize: 1024 * 1024 * 1024 }
  });

  // 设置响应头
  responseStream.setContentType('application/json');
  responseStream.write(JSON.stringify({ status: 'start processing' }));

  // 处理文件字段:直接流式上传到S3
  bb.on('file', async (fieldname, fileStream, filename, _, mimetype) => {
    try {
      const uploadParams = {
        Bucket: 'your-target-bucket',
        Key: `uploads/${Date.now()}-${filename}`,
        Body: fileStream,
        ContentType: mimetype
      };
      await s3Client.send(new PutObjectCommand(uploadParams));
      responseStream.write(JSON.stringify({ message: `uploaded ${filename} successfully` }));
    } catch (err) {
      responseStream.write(JSON.stringify({ error: err.message, file: filename }));
    } finally {
      fileStream.resume(); // 确保流被消费,避免Busboy阻塞
    }
  });

  // 处理普通表单字段
  bb.on('field', (fieldname, value) => {
    console.log(`Form field ${fieldname}: ${value}`);
  });

  // 解析完成后结束响应
  bb.on('finish', () => {
    responseStream.write(JSON.stringify({ status: 'all files processed' }));
    responseStream.end();
  });

  // 处理解析错误
  bb.on('error', (err) => {
    console.error('Busboy parse error:', err);
    responseStream.write(JSON.stringify({ error: err.message }));
    responseStream.end();
  });

  // 将Lambda请求流直接pipe到Busboy
  event.requestStream.pipe(bb);
});

关键细节说明

  • 原生流处理:直接使用 event.requestStream 作为数据源,这是Lambda提供的真实可读流,而非模拟的Express请求对象,完全适配大文件流式解析。
  • Busboy配置:必须传入小写请求头,否则无法正确识别multipart边界;设置fileSize限制匹配你的1GB需求。
  • S3流式上传:将Busboy输出的文件流直接作为S3上传的Body,全程无内存缓冲,避免内存溢出。
  • 流的强制消费:在file事件中必须调用fileStream.resume(),即使不处理文件内容,否则Busboy会停止解析后续数据。
  • 实时响应:通过responseStream实时返回处理状态,无需等待所有文件上传完成再响应。

注意事项

  • Lambda超时设置:处理1GB文件需足够超时时间,建议设为15分钟(Lambda最大超时值)。
  • 内存配置:至少分配512MB内存,提升IO处理性能。
  • 网关配置:API Gateway需开启流式支持(Payload Format Version设为2.0,启用流式选项),确保请求流能完整传递到Lambda。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 17:03:15