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

Node.js Lambda调用S3 PutObject无法从EFS上传文件求助

Node.js Lambda将EFS文件迁移至S3无上传问题排查与修复

问题核心

你的Lambda函数能成功在EFS生成压缩文件,但S3上传操作未触发且无报错,循环仅完成压缩步骤就结束。

问题根源

  1. forEach不支持异步等待:forEach循环不会等待内部async函数执行完成,Lambda主线程会直接走完,导致S3上传的异步操作还没开始就被终止。
  2. 循环内提前return:符合条件的文件处理到一半就return,直接结束Lambda函数,后续上传逻辑完全没机会执行。
  3. 同步FS方法阻塞事件循环:readdirSync、statSync这类同步方法会阻塞Node.js事件循环,导致异步的S3上传请求无法被调度执行。
  4. S3 Key冗余拼接:你把已经带.zip的文件名又重复加了一次.zip,导致Key变成xxx.zip.zip,虽然不是上传失败的直接原因,但会导致S3文件命名不符合预期。

修复方案

1. 替换forEach为for...of循环

for...of原生支持async/await,能确保每个文件的异步操作完成后再处理下一个。

2. 移除循环内的return语句

把return放在整个函数末尾,确保所有文件处理完成后再返回响应。

3. 改用异步FS方法

使用fs.promises下的异步方法替代同步方法,避免阻塞事件循环。

4. 修正S3 Key冗余拼接

直接使用生成的zip文件名作为S3 Key,不要重复加.zip。

5. 完善错误捕获

确保文件流和S3上传的错误都能被捕获并打印。

修复后的完整代码

import { PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
import fs from 'fs/promises';
import path from 'path';
import ZipLocal from 'zip-local';

const s3Client = new S3Client({ region: 'us-west-2' });

export const lambdaHandler = async (event, context) => {
    try {
        const efsDirectory = "/mnt/data/";
        const files = await fs.readdir(efsDirectory);

        for (const file of files) {
            const filePath = path.join(efsDirectory, file);
            console.log("当前处理文件:", file);
            console.log("文件路径:", filePath);

            const response = await fs.stat(filePath);
            console.log("文件创建时间:", response.birthtime);

            const fileBirthTime = response.birthtime;
            const currentTime = new Date();
            const timeDifference = currentTime - fileBirthTime;
            const timeDifferenceInMin = (timeDifference / 1000) / 60;
            console.log("文件创建时长(分钟):", timeDifferenceInMin);

            if (timeDifferenceInMin >= 1) {
                console.log("文件创建时长≥1分钟,开始处理");

                const filePathWithoutExt = path.parse(file).name;
                const zipFilePath = path.join(efsDirectory, `${filePathWithoutExt}.zip`);
                console.log("压缩文件路径:", zipFilePath);

                // 同步压缩文件(如果需要异步可改用zip-local的异步API)
                ZipLocal.sync.zip(filePath).compress().save(zipFilePath);
                console.log("文件压缩完成");

                // 创建文件流并监听错误
                const fileStream = fs.createReadStream(zipFilePath);
                fileStream.on('error', (error) => {
                    console.error("文件流错误:", error.message);
                    throw error;
                });

                const s3Key = path.basename(zipFilePath);
                console.log("S3 Key:", s3Key);

                const bucketName = "matomo-lambda-test-bucket";
                const params = {
                    Bucket: bucketName,
                    Key: s3Key,
                    Body: fileStream
                };

                console.log("S3上传参数:", params);
                const uploadRes = await s3Client.send(new PutObjectCommand(params));
                console.log("S3上传成功响应:", uploadRes);

                const bucketUrl = `https://${bucketName}.s3.us-west-2.amazonaws.com/${s3Key}`;
                console.log("S3文件URL:", bucketUrl);

                // 删除原文件
                await fs.unlink(filePath);
                console.log("已删除原文件:", file);

                // 打印当前EFS目录文件
                const remainingFiles = await fs.readdir(efsDirectory);
                console.log("当前EFS目录剩余文件:", remainingFiles);
            } else {
                console.log("文件创建时长<1分钟,跳过处理");
            }
        }

        return {
            statusCode: 200,
            body: JSON.stringify({
                message: '所有符合条件的文件处理完成'
            })
        };

    } catch (err) {
        console.error("函数执行错误:", err);
        return {
            statusCode: 500,
            body: JSON.stringify({ error: err.message })
        };
    }
};

额外注意事项

  • 调整Lambda超时时间:如果处理大文件,需将Lambda超时时间设置足够长(比如5分钟),避免上传未完成就被终止。
  • 检查权限配置:Lambda执行角色需要具备S3的PutObject权限,以及EFS的读写权限。
  • 验证EFS挂载:确保Lambda已正确挂载EFS,/mnt/data/路径可正常访问。

内容的提问来源于stack exchange,提问作者Rehan CH

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 12:55:20