【问题标题】:load S3 file in Lambda with Node.js version 8.10使用 Node.js 版本 8.10 在 Lambda 中加载 S3 文件
【发布时间】:2019-03-01 07:24:17
【问题描述】:

我一直在尝试(但失败)使用 Node 版本 8.10 中的 s3.getObject 从 S3 存储桶加载文件。

我发现了一篇很棒的帖子,其中回复了几乎可以正常工作的 here,但语法在 8.10 中不太适用,无论我如何重新安排代码,我都无法使其正常工作。

var AWS = require('aws-sdk')
var s3 = new AWS.S3();

var fileData = null;

exports.handler = (event, context, callback) => {
    console.log('I am in the main procedure');
    var params = {
        Bucket: "change_for_your_bucket",
        Key:  "change_to_your_json_file"
    };

    fetchDataFromS3(params);
    console.log('I am in the main procedure, the function above should be waiting but it is not');
    waitForFileLoadBeforeDoingSomething(event, context, callback);

    const s = JSON.stringify(fileData.Body.toString('utf-8'));
    console.log(`this is the file: ${s}`);
    console.log('I have the file!(dg.2)');    

};

function fetchDataFromS3(params)
{
    console.log('-------------- fetchDataFromS3:Start -------------------------');
    // gets the object from s3 => promise
    const uploadPromise = s3.getObject(params).promise();

    // returns the body of the s3 object
    uploadPromise
            .then(function(data) {
                console.log("successfully downloaded data");
                fileData = data.Body.toString();

            })
            .catch(function download(err) {console.log(err,err.stack); throw err;});


    console.log('-------------- fetchDataFromS3:Done -------------------------');
}



function waitForFileLoadBeforeDoingSomething(event, context, callback){
    if(!fileData){
        console.log('No file available to me as yet, lets sleep for a bit');
        setTimeout(function(){
            waitForFileLoadBeforeDoingSomething(event, context, callback);
        }, 300);
    } 
}

输出如下。

Function Logs:
START RequestId: cb16f155-c0d7-11e8-ad01-f5991c5adaaf Version: $LATEST
2018-09-25T15:29:29.759Z    cb16f155-c0d7-11e8-ad01-f5991c5adaaf    I am in the main procedure
2018-09-25T15:29:29.759Z    cb16f155-c0d7-11e8-ad01-f5991c5adaaf    -------------- fetchDataFromS3:Start -------------------------
2018-09-25T15:29:29.811Z    cb16f155-c0d7-11e8-ad01-f5991c5adaaf    -------------- fetchDataFromS3:Done -------------------------
2018-09-25T15:29:29.811Z    cb16f155-c0d7-11e8-ad01-f5991c5adaaf    I am in the main procedure, the function above should be waiting but it is not
2018-09-25T15:29:29.811Z    cb16f155-c0d7-11e8-ad01-f5991c5adaaf    No file available to me as yet, lets sleep for a bit
2018-09-25T15:29:29.812Z    cb16f155-c0d7-11e8-ad01-f5991c5adaaf    TypeError: Cannot read property 'Body' of null
    at exports.handler (/var/task/dg3.js:17:39)

您可以看到我没有点击“成功下载数据”行,如果我犯了一个错误并且该函数仍在异步运行,或者如果我获得了 promise 的语法,我无法解决错了。

【问题讨论】:

    标签: node.js amazon-s3 aws-lambda


    【解决方案1】:

    首先,您必须更改您的入口点方法。就像您在尝试使用 8.10 节点运行时之前提到的那样,然后是以下代码部分:

    exports.handler = (event, context, callback) => {}
    

    你必须改为:

    export async function <function_name>(event) {}
    

    参考:https://aws.amazon.com/blogs/compute/node-js-8-10-runtime-now-available-in-aws-lambda/

    那么你到那个函数的路径应该是:

    <module_name>.<function_name>
    

    另外,您不需要以下代码部分:

    function waitForFileLoadBeforeDoingSomething(event, context, callback){
        if(!fileData){
            console.log('No file available to me as yet, lets sleep for a bit');
            setTimeout(function(){
                waitForFileLoadBeforeDoingSomething(event, context, callback);
            }, 300);
        } 
    }
    

    然后摆脱 var 声明。不要乱用范围。只需使用:

    const AWS = require('aws-sdk');
    

    下一步是创建一个 S3 实例:

    const S3 = new AWS.S3({region: process.env.AWS_REGION, apiVersion: '2006-03-01'});
    // with region of your AWS account and current API verstion;
    

    为您的 fetch 方法声明参数:

    const params = 
    {
      Bucket: 'STRING_VALUE', // a path to your Bucket
      Key: 'STRING_VALUE' // a key (literally a path to your file)
    }
    

    参考:https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#getObject-property

    而且您不必对事件进行字符串化,因为它已经被字符串化了:

    const s = JSON.stringify(fileData.Body.toString('utf-8'));
    

    最后:

    try
    {
        const result = await S3.getObject(params).promise();
        // if successful then:
        console.log(`Check the result: ${result}`);
    }
    catch (ex) // if an error occured
    {
         console.error(ex);
    }
    

    另外,请确保运行时间为 5 分钟(仅用于调试目的,您可以调整后)并增加 lambda 的内存(也用于测试目的)。

    【讨论】:

    • 感谢您的出色回应,如果真的对我的理解有所帮助,在我弄明白之前,我再次短暂地将 S3 getobject 调用分离到一个单独的函数中,我不得不稍微更改事件处理程序声明让它工作(我不知道为什么)。我将发布我创建的代码的更新版本。
    • 由于我无法在评论中发布长代码 sn-ps 此处是代码工作版本的链接。 link
    猜你喜欢
    • 2021-12-14
    • 2019-09-27
    • 2015-10-05
    • 1970-01-01
    • 1970-01-01
    • 2018-08-04
    • 2016-12-19
    • 2018-08-29
    • 2020-07-08
    相关资源
    最近更新 更多