如何将Express.js分片上传函数改写为Node.js 18版AWS Lambda?
将Express.js分片上传S3的接口改写为Node.js 18 AWS Lambda函数
需要把接收文件分片并上传至S3存储桶的Express.js函数,改写为适用于Node.js 18的AWS Lambda函数,原Express.js代码如下:
const upload = multer() // Receive chunk and write it to S3 bucket app.post('/upload', upload.single("file"), (req, res) => { const { index, fileName } = req.body; const file = req.file; const s3Params = { Bucket: bucketName, Key: fileName, Body: file.buffer, PartNumber: Number(index) + 1, UploadId: req.query.uploadId }; s3.uploadPart(s3Params, (err, data) => { if (err) { console.log(err); return res.status(500).json({ success: false, message: 'Error uploading chunk' }); } return res.json({ success: true, message: 'Chunk uploaded successfully' }); }); });
由于Node.js 18的AWS Lambda默认集成AWS SDK v3,且Lambda处理API Gateway请求时需自行解析multipart/form-data(无法直接使用multer),这里使用busboy解析请求体,以下是改写后的Lambda函数:
import { S3Client, UploadPartCommand } from "@aws-sdk/client-s3"; import Busboy from "busboy"; import { promisify } from "util"; import stream from "stream"; const pipeline = promisify(stream.pipeline); const s3Client = new S3Client({ region: "你的AWS区域" }); const bucketName = "你的存储桶名称"; exports.handler = async (event) => { return new Promise((resolve, reject) => { const busboy = Busboy({ headers: { "content-type": event.headers["Content-Type"] || event.headers["content-type"], }, }); let chunkData = {}; let fileBuffer = Buffer.from(""); // 解析表单字段 busboy.on("field", (fieldname, value) => { chunkData[fieldname] = value; }); // 解析文件分片内容 busboy.on("file", (_, file) => { file.on("data", (data) => { fileBuffer = Buffer.concat([fileBuffer, data]); }); }); // 解析完成后执行S3上传 busboy.on("finish", async () => { try { const { index, fileName } = chunkData; const uploadId = event.queryStringParameters?.uploadId; if (!index || !fileName || !uploadId) { return resolve({ statusCode: 400, body: JSON.stringify({ success: false, message: "缺少必要参数" }), }); } const uploadParams = { Bucket: bucketName, Key: fileName, Body: fileBuffer, PartNumber: Number(index) + 1, UploadId: uploadId, }; const command = new UploadPartCommand(uploadParams); await s3Client.send(command); resolve({ statusCode: 200, body: JSON.stringify({ success: true, message: "Chunk uploaded successfully" }), }); } catch (err) { console.error(err); resolve({ statusCode: 500, body: JSON.stringify({ success: false, message: "Error uploading chunk" }), }); } }); // 处理解析错误 busboy.on("error", (err) => { console.error(err); reject({ statusCode: 500, body: JSON.stringify({ success: false, message: "Failed to parse request" }), }); }); // 将base64编码的请求体传入busboy解析 const bodyBuffer = Buffer.from(event.body, event.isBase64Encoded ? "base64" : "utf8"); busboy.end(bodyBuffer); }); };
注意事项
- 依赖处理:Lambda需要
busboy包,可通过npm install busboy后打包部署,或创建Lambda层统一管理依赖。 - API Gateway配置:需将
multipart/form-data添加到API Gateway的Binary Media Types列表中,防止请求体编码异常。 - IAM权限:Lambda执行角色必须包含
s3:UploadPart权限,且允许访问目标S3存储桶。 - 区域配置:替换代码中的
"你的AWS区域"为实际使用的AWS区域(如us-east-1)。
内容的提问来源于stack exchange,提问作者texi
相关产品推荐
相关产品推荐

