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
相关产品推荐
相关产品推荐

