【问题标题】:How to extract .zip files to a directory within a lambda function如何将 .zip 文件提取到 lambda 函数中的目录
【发布时间】:2020-06-17 10:23:09
【问题描述】:

我遇到的问题是,当我针对 .zip 文件测试函数时,当函数到达 fs.createReadStream&Zip 时,函数没有运行或返回错误,我想了解什么我做错了,正确的解决方案看起来如何。

const AWS = require('aws-sdk');
const fs = require('fs');
const mkdirp = require('mkdirp');
const unzipper = require('unzipper');

exports.handler = async (event, context) => {

    // Variables for bucket init
    let sourceBucket = 'am-doc-mgmt-s3-dev-landing';
    let storageBucket = 'am-doc-mgmt-s3-dev';

    // Variables for folder init and Buffer config
    const localZippedFolder = '/tmp/ZippedStudentData/';
    const localUnzippedFolder = '/tmp/UnzippedStudentData/';

    const ZipBuffer = Buffer.from(localZippedFolder, 'base64');
    const UnzippedBuffer = Buffer.from(localUnzippedFolder, 'base64');

    // Inits AWS s3 Bucket and DynamoDB
    let s3 = new AWS.S3();
    let docClient = new AWS.DynamoDB.DocumentClient({ region: 'us-east-1' });

    // Gets the file bucket and file name of the s3 object from context
    let fileBucket = event.Records[0].s3.bucket.name;
    let fileName = event.Records[0].s3.object.key;
    let params = {
        Bucket: fileBucket,
        Key: fileName
    };

    // Creates temporary variables
    let tempFile = localZippedFolder + fileBucket;
    let tempUnzippedFile = localUnzippedFolder + fileBucket;

    // Make Directories for Zipped and Unzipped files
    try {
        const zipDirFolder = await mkdirp(localZippedFolder, { recursive: true })
        const unZipDirFolder = await mkdirp(localUnzippedFolder, { recursive: true });
        console.log('SUCCESS: unzipped directory created!');
        console.log('SUCCESS: zipped directory create!')

    // Download files from s3 Bucket
        let newFolder = await s3.getObject(params).promise()
        .then(data => {
            console.log(data);
            return data;
        });

    // Extract files from zipped folder and store them in a local directory
       fs.createReadStream(params.Key)
        .pipe(unzipper.Extract({path: unZipDirFolder}))
        .on('finish', () => {
             fs.readdir(unZipDirFolder);
        }).on('error', (err) => {
             // error handling here
             console.log(err);
    });

    }   
     catch (error) {
        console.log(error);
    }
};

错误:没有从 fs.createReadStream 函数返回任何内容。就好像它只是跳过了该功能。

【问题讨论】:

  • 因此,您的结果将是fs.readdir(unZipDirFolder); 所在的位置。您需要在该事件处理程序内使用结果。你在这里期待什么?结果是异步检索的。使用这种结构,您可以使用它们的唯一位置就是您执行 fs.readdir(unZipFolder) 的地方(这也是异步的,因此您也必须适当地执行此操作)。
  • 您希望如何调用和使用这个async 导出的函数?究竟是什么不工作?
  • 它跳过了fs.createReadStream().pipe(),因为它都是异步的。当您收到 finish 事件时,它就完成了。同时,它继续运行其他东西。
  • 好的,为了解决这个问题,我需要从当前位置删除 fs.readdir() 函数并在其位置返回结果?
  • 不,从事件处理程序内部返回对您没有任何好处。这不会从您的主要功能返回。请参阅我在下面添加的承诺包装器(与我在您的其他问题中向您展示的概念相同)。

标签: javascript node.js asynchronous aws-lambda async-await


【解决方案1】:

说实话,很难弄清楚您真正想要解决的问题是什么,因为您对此并不是很具体。如果您希望包含 async 的函数在解压缩完成之前不解析它的承诺,您可以将流包装在这样的承诺中:

const AWS = require('aws-sdk');
const fs = require('fs');
const mkdirp = require('mkdirp');
const unzipper = require('unzipper');

exports.handler = async (event, context) => {

    // Variables for bucket init
    let sourceBucket = 'am-doc-mgmt-s3-dev-landing';
    let storageBucket = 'am-doc-mgmt-s3-dev';

    // Variables for folder init and Buffer config
    const localZippedFolder = '/tmp/ZippedStudentData/';
    const localUnzippedFolder = '/tmp/UnzippedStudentData/';

    const ZipBuffer = Buffer.from(localZippedFolder, 'base64');
    const UnzippedBuffer = Buffer.from(localUnzippedFolder, 'base64');

    // Inits AWS s3 Bucket and DynamoDB
    let s3 = new AWS.S3();
    let docClient = new AWS.DynamoDB.DocumentClient({ region: 'us-east-1' });

    // Gets the file bucket and file name of the s3 object from context
    let fileBucket = event.Records[0].s3.bucket.name;
    let fileName = event.Records[0].s3.object.key;
    let params = {
        Bucket: fileBucket,
        Key: fileName
    };

    // Creates temporary variables
    let tempFile = localZippedFolder + fileBucket;
    let tempUnzippedFile = localUnzippedFolder + fileBucket;

    // Make Directories for Zipped and Unzipped files
    try {
        const zipDirFolder = await mkdirp(localZippedFolder, { recursive: true })
        const unZipDirFolder = await mkdirp(localUnzippedFolder, { recursive: true });
        console.log('SUCCESS: unzipped directory created!');
        console.log('SUCCESS: zipped directory create!')

        // Download files from s3 Bucket
        let newFolder = await s3.getObject(params).promise();

        await new Promise((resolve, reject) => {
            // Extract files from zipped folder and store them in a local directory
           fs.createReadStream(params.Key)
                .pipe(unzipper.Extract({path: unZipDirFolder}))
                .on('finish', resolve);
                .on('error', reject);
        });

    } catch (error) {
        console.log(error);
        // rethrow error so caller sees the error
        throw error;
    }
};

而且,使用此导出函数的调用者必须在返回的承诺上使用 .then()await 才能知道何时完成。并且,在await 周围使用.catch()try/catch 来捕获错误。

【讨论】:

  • 好吧,我的目标是解压缩文件并能够在目录中查看解压缩文件的日志。运行代码时,这是返回的错误 2020-03-04 21:14:11.459 {"errorType":"Error","errorMessage":"ENOENT: no such file or directory, open 'Jerry-user-data .zip'"
  • @brycent - 而且,该消息是在哪里出现的?这可能不在此代码中。在您展示从头到尾的整个代码路径并显示您遇到了什么错误以及您在哪里遇到错误并描述您期望的结果之前,我们真的无法为您提供非常有效的帮助。
  • @brycent - 这个导出的函数是异步的。它返回一个承诺。这个函数的调用者(使用我添加的代码)在尝试读取解压缩文件之前必须使用该承诺知道它何时完成。
  • 我收到的错误信息发生在代码到达 await new promise 函数时,然后 lambda 超时。它可能与解压缩文件所需的时间有关
  • 我认为这是我创建引发错误的临时目录的方式,这就是为什么当它到达函数时它可能会破坏它
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-06-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-25
  • 2017-11-04
相关资源
最近更新 更多