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

如何将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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 20:56:26