使用 AWS Lambda 从 AWS S3 读取和提取巨大的 zip 文件

Posted

技术标签:

【中文标题】使用 AWS Lambda 从 AWS S3 读取和提取巨大的 zip 文件【英文标题】:Read and extract huge zip file from AWS S3 with AWS Lambda 【发布时间】:2017-05-11 11:34:33 【问题描述】:

我正在开发数据管理应用程序,客户端可以在AWS S3 上上传zip file(approx 250 MB) 和多个text files(approx 1500 MB)

但由于 aws lamda 的内存有限(最大 1536MB 大小),我能够提取 (50 MB) 的 zip 文件和 (500 MB) 的提取文件。

由于我需要在提取时对提取的文件添加一些验证,然后我必须将文件的所有内容存储到数据库中。

现在我将文件的内容存储在aws-lambda tmp location 中,它也有最大 500MB 可以使用的限制。

任何有助于通过验证完成上述任务的流式传输概念都会对我有所帮助。

我可以使用EC2, ECS,但现在我只想使用AWS-Lambda

使用此代码,我将提取 zip 文件并将其上传到另一个 S3 存储桶。

任何其他概念(例如流式传输)都会对我有所帮助,因为我对流式传输概念不太熟悉,我在这里提出一些想法来解决我的问题。

s3.getObject(params, (err, data) => 
    if (err) 
        console.log('Error', err);
        var message = `Error getting object $key from bucket $bucket. Make sure they exist and your bucket is in the same region as this function.`;
        console.log(message);
        //  callback(message);
     else 
        console.log('Started to buffer data');
        JSZip.loadAsync(data.Body).then(function(zip) 
            fs.writeFile('temp/hello.txt', 'New file added for testing');
            async.each(zip.files, function(item, cb1) 
                if (!item.dir && item.name.includes('nightly')) 
                    zip.file(item.name).async("text").then(function(content) 
                        fs.writeFile('temp/' + item.name.replace(/^.*[\\\/]/, ''), content, function(err) 
                            if (err) throw err;
                            cb1();
                        );
                    );
                 else 
                    cb1();
                
            , function(err, result) 
                var zipObj = new JSZip();
                fs.readdir('./temp', function(err, files) 
                    console.log(files);
                    async.each(files, function(file, cb2) 
                        fs.readFile('./temp/' + file, 'utf-8', function(err, content) 
                            if (err) 
                                return err;
                            
                            zipObj.file(file, content);
                            cb2();
                        );
                    , function(err) 
                        zipObj.generateAsync(
                                type: "nodebuffer"
                            )
                            .then(function(content) 
                                console.log(content);
                                deleteFiles(['./temp/*'], function(err, paths) 
                                    console.log('Deleted files/folders:\n', paths.join('\n'));
                                );

                                s3.putObject(
                                    Bucket: 'abtempb',
                                    Key: 'temp/records.zip',
                                    Body: content
                                , function(err, result) 
                                    if (result && result.ETag) 
                                        console.log('uploaded file: ', result.ETag);
                                    
                                    console.log('Error ', err);
                                );
                            );
                    );
                );
            );
        );
    
);

谢谢

【问题讨论】:

使用流式提取。这将限制执行提取所需的内存量。 你能提供一些代码或任何参考来获取流概念吗? 将文件从 S3 下载到本地文件系统,然后使用 nodejs 流 zip 模块,类似于 github.com/antelle/node-stream-zip 您可能还会在处理大文件时面临 lambda 超时(15 分钟 - 曾经是 5 分钟)。以编程方式生成的 s3-presigned url(或者如果您不想将 s3 公开,则使用 cloudfront)是否适用于您的案例?那么您就不必成为传输数据的中间人。 可以是gzip文件吗?还是只压缩? 【参考方案1】:

您现在可以在 Lambda 上挂载 EFS 卷。详情可见here。

【讨论】:

以上是关于使用 AWS Lambda 从 AWS S3 读取和提取巨大的 zip 文件的主要内容,如果未能解决你的问题,请参考以下文章

使用AWS Lambda从AWS SNS读取时修改JSON消息

使用 AWS Lambda 从 AWS SNS 读取时修改 JSON 消息

AWS Lambda使用S3

带有Java的AWS Lambda无法从S3获取文件

Zip 文件在使用节点和 AWS lambda 从 SFTP 服务器发布到 S3 后无法展开

使用 AWS Lambda (Python 3) 读取存储在 S3 中的 Parquet 文件