如何用NodeJS+Typescript通过Lambda秒级上传1-2GB文件到S3?
1-2GB文件通过NodeJS+TS Lambda秒级上传S3的最优方案
Lambda天生适合轻量计算,直接处理1-2GB文件上传会受限于执行时间、网络传输效率,完全没必要。最优解是预签名URL方案:Lambda只生成授权的临时上传URL,客户端拿到后直接和S3交互完成上传,Lambda仅做轻量的签名生成操作,执行时间毫秒级,轻松实现秒级响应。
一、Lambda核心实现(NodeJS+TS)
用AWS SDK v3更轻量化,适配Lambda的执行环境:
- 安装依赖:
npm install @aws-sdk/client-s3 @aws-sdk/s3-request-presigner
- 完整代码:
import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3"; import { getSignedUrl } from "@aws-sdk/s3-request-presigner"; // 初始化S3客户端,Lambda会自动加载执行角色的权限,无需硬编码密钥 const s3Client = new S3Client({ region: "你的S3桶所在区域" }); export const handler = async (event: any) => { // 从请求参数中获取文件名、文件类型(如果是API Gateway触发,从event.body解析) const { fileName, fileType } = JSON.parse(event.body || "{}"); // 校验必填参数 if (!fileName || !fileType) { return { statusCode: 400, body: JSON.stringify({ message: "缺少fileName或fileType参数" }), }; } try { // 构造S3上传命令 const putCommand = new PutObjectCommand({ Bucket: "你的S3桶名称", Key: `user-uploads/${fileName}`, // 自定义文件在S3中的存储路径 ContentType: fileType, // 可选:设置文件访问权限,比如公开读 // ACL: "public-read" }); // 生成预签名URL,有效期设为1小时(可根据业务调整) const signedUploadUrl = await getSignedUrl(s3Client, putCommand, { expiresIn: 3600 }); return { statusCode: 200, body: JSON.stringify({ uploadUrl: signedUploadUrl, tip: "直接用PUT请求该URL上传文件即可" }) }; } catch (error) { return { statusCode: 500, body: JSON.stringify({ message: "生成预签名URL失败", error: error.message }) }; } };
二、Lambda权限配置
给Lambda的执行IAM角色添加S3的PutObject权限,示例策略:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "s3:PutObject", "Resource": "arn:aws:s3:::你的S3桶名称/user-uploads/*" } ] }
三、客户端上传示例(浏览器/NodeJS)
拿到预签名URL后,直接发起PUT请求上传文件:
// 浏览器端示例 async function uploadToS3(uploadUrl, file) { const response = await fetch(uploadUrl, { method: "PUT", body: file, headers: { "Content-Type": file.type } }); return response.ok; } // NodeJS端示例 const fs = require("fs"); const axios = require("axios"); async function uploadFromNode(uploadUrl, filePath) { const fileStream = fs.createReadStream(filePath); const response = await axios.put(uploadUrl, fileStream, { headers: { "Content-Type": "application/octet-stream" // 根据文件类型调整 } }); return response.status === 200; }
四、关键注意事项
- 文件大小兼容:S3单PUT请求最大支持5GB,完全覆盖1-2GB的需求,不需要分片上传。
- Lambda资源配置:只需要给Lambda分配128MB内存即可,因为仅做签名生成,内存占用极低,执行时间通常在100ms以内。
- 安全控制:预签名URL的有效期不要设置太长,建议1小时以内;同时通过IAM角色严格限制Lambda的S3操作范围,避免权限过大。
- 触发方式:建议用API Gateway触发Lambda,客户端通过HTTP请求获取预签名URL,流程更规范,也方便做身份验证(比如Cognito)。
内容的提问来源于stack exchange,提问作者systemdebt
相关产品推荐
相关产品推荐

