首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >AWS JSON Lambda事件-获取、更新,然后从同一存储桶中放入S3文件

AWS JSON Lambda事件-获取、更新,然后从同一存储桶中放入S3文件
EN

Stack Overflow用户
提问于 2019-01-07 06:28:11
回答 2查看 6.1K关注 0票数 0

我正在修改亚马逊S3教程找到的here的AWS Lambda,这样它就可以简单地--

  • 读取已经驻留在该存储桶中的JSON文件(内容索引),
  • 使用新创建的密钥(该存储桶中触发了这个Lambda的新“文件夹”)更新它,
  • ,然后保存(上传)更新后的JSON文件。

CLARIFICATION:当在存储桶中创建了文件夹对象时,存储桶才会触发Lambda函数。内容索引(index.json)已驻留在存储桶中。因此,存储桶将具有文件夹(例如,{ index.json -1,folder-2,folder-n})和文件夹。每次添加新文件夹时,都会将其添加到JSON数组中。

具体地说,在我的例子中,我有一个根(目标)存储桶,它将包含由Elemental MediaConvert创建的一系列文件夹。每个文件夹代表一个新的视频;并且在每个文件夹内是可以提供给不同设备的不同格式。回到根级别,我有index.json,它是这些视频文件夹的数组;它是内容索引。现在,我可以修改作为MediaConvert流一部分的Lambda。但我会在另一个时间考虑这一点。在这里,我只想在每次MediaConvert写一个新的视频文件夹时触发一个新的S3 Lambda……这只是一些随机的GUID。

我正在学习Node JS,这是我第一次使用你在这里看到的一些结构和调用。(我至少意识到这个表单比使用回调更干净、更清晰。)

因为这将是棘手的(对我来说!)要将其作为Lambda函数进行测试,是否有人能指出任何明显的错误??

另外,谁能给我一些指导,告诉我如何使用亚马逊S3事件数据手动测试这个Lambda函数(在配置实际存储桶以发布所需事件之前)?我认为我需要event.json来指定新创建的文件夹的名称,这样就可以将它添加到我的index.json中,它也在同一个bucket中。

下面是我的代码:

代码语言:javascript
复制
// dependencies
var async = require('async');
var AWS = require('aws-sdk');
var util = require('util');

// constants
//const DEST_FOLDER = 'my-triggering-bucket';
const CONTENT_INDEX_FILENAME = 'index.json';

// get reference to S3 client
var s3 = new AWS.S3();

exports.handler = function(event, context, callback) {
    // Read options from the event.
    // Need the new folder (key) that's been added to the bucket...
    console.log("Reading options from event:\n", util.inspect(event, {depth: 5}));

    // I assume this is the triggering bucket...
    var triggerBucket = event.Records[0].s3.bucket.name;

    // And I assume this is the folder that was added and caused the trigger
    var newKey    = decodeURIComponent(event.Records[0].s3.object.key);

    const indexKey = CONTENT_INDEX_FILENAME;

    // Get the content index and add the newly created dir to it
    async.waterfall([
        function download(next) {
            // Download the content index from S3 into a buffer.
            s3.getObject({
                    Bucket: triggerBucket,
                    Key: indexKey
                },
                next);
        },
        function update(response, next) {
          // Update the content index with the new dir that was added
          console.log('UPDATE...');
          var obj = JSON.parse(response);
          obj.push(newKey);
          var jsonStr = JSON.stringify(obj);
          next(null, jsonStr.ContentType, jsonStr);
        },
        function upload(contentType, data, next) {
            // Stream the updated content index back
            s3.putObject({
                    Bucket: triggerBucket,
                    Key: indexKey,
                    Body: data,
                    ContentType: contentType
                },
                next);
            }
        ], function (err) {
            if (err) {
                console.error('error: ' + err);
            } else {
                console.log('Success);
            }

            callback(null, "message");
        }
    );
};

UPDATE我放弃了这种方法,转而通过另一种方式更新内容索引,这样就不会有失控执行的风险。我直接发现,当一个人的设计没有提供可靠的事件通知过滤器时,尝试在存储桶中触发特定的createObject事件并不是一个好主意。(我无法过滤简单/的后缀。)另外,我期望一个单独的文件夹键对象创建事件来触发我的Lambda,但实际上在这个新的根级文件夹中创建的其他文件夹和键也会触发我的Lambda。因此,这将我发送到视频转换工作流中来修改Lambda,该Lambda通知工作流成功完成,从而更新我的内容索引。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-01-07 08:11:45

您的Lambda只会在存储桶中创建/删除/修改新对象时触发,具体取决于您的配置。如果你在存储桶中创建一个新的文件夹,它不会触发你的Lambda。您可以在Lambda Node.js 8.1运行时中使用async/await语法来简化代码。

Lambda处理程序

代码语言:javascript
复制
var AWSS3 = require('aws-sdk/clients/s3');
const CONTENT_INDEX_FILENAME = 'index.json';
var s3 = new AWSS3();

exports.handler = async (event) => {

  try {
    console.log('Event', JSON.stringify(event));

    // Bucket name.
    const triggerBucket = event.Records[0].s3.bucket.name;

    // New key added.
    const newKey = event.Records[0].s3.object.key;

    // Assuming only folder name is to be added in the list. If object 
    // is added in the bucket root then it will be ignored.
    if (newKey.indexOf('/') > -1) {

      // Get existing data.
      let existing = await s3.getObject({
        Bucket: triggerBucket,
        Key: CONTENT_INDEX_FILENAME
      }).promise();

      // Parse JSON object.
      let existingData = JSON.parse(existing.Body);

      // Get the folder name.
      const folderName = newKey.substring(0, newKey.indexOf("/"));

      // Check if we have an array.
      if (!Array.isArray(existingData)) {
        // Create array.
        existingData = [];
      }

      existingData.push(folderName);

      await s3.putObject({
        Bucket: triggerBucket,
        Key: CONTENT_INDEX_FILENAME,
        Body: JSON.stringify(existingData),
        ContentType: 'application/json'
      }).promise();

      console.log(`Added new folder name ${folderName}`);

      return folderName;

     } else {
         console.log('Key was added in bucket root.');
         return 'Ignored';
     }
    };
  }
  catch(err) {
    return err;
  }

本地运行的

在项目根目录中创建一个event.json文件。在event.json中添加以下内容。

代码语言:javascript
复制
{
  "Records":[
    {
      "s3":{
        "bucket":{
        "name": "your_bucket_name"
    },
    "object":{
      "key": "your_folder/your_file.json"
    }
   }
  }
 ]
}

全局下载lambda本地包。

npm install -g lambda-local

最后对其进行测试:

通过传递上面创建的event.json文件在本地运行函数。

lambda-local -l path/to/function.js -e event.json

票数 1
EN

Stack Overflow用户

发布于 2019-01-07 06:45:52

至于本地测试,我之前使用过https://www.npmjs.com/package/aws-lambda-local,它对我来说工作得很好。

只需查看亚马逊网络服务的文档,例如S3事件json数据

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54066524

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档