63

我想知道是否可以为 AWS 设置一个 lambda 函数,只要将新文本文件上传到 s3 存储桶中就会触发。在函数中,我想获取文本文件的内容并以某种方式处理它。我想知道这是否可能......?

例如,如果我上传 foo.txt,内容为 foobarbaz,我想以某种方式在我的 lambda 函数中获取 foobarbaz,这样我就可以用它做一些事情。我知道我可以从 getObject 或类似方法中获取元数据。

谢谢!

4

3 回答 3

72

S3 对象键和存储桶名称通过event参数传递到您的 Lambda 函数。然后,您可以从 S3 获取对象并读取其内容。

从 Lambda 中检索存储桶和对象键的基本代码event如下:

exports.handler = function(event, context, callback) {
   const bkt = event.Records[0].s3.bucket.name;
   const key = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, ' '));
};

获得存储桶和密钥后,您可以调用 getObject 来检索对象:

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

exports.handler = function(event, context, callback) {
    
    // Retrieve the bucket & key for the uploaded S3 object that
    // caused this Lambda function to be triggered
    const Bucket = event.Records[0].s3.bucket.name;
    const Key = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, ' '));

    // Retrieve the object
    s3.getObject({ Bucket, Key }, function(err, data) {
        if (err) {
            console.log(err, err.stack);
            callback(err);
        } else {
            console.log("Raw text:\n" + data.Body.toString('ascii'));
            callback(null, null);
        }
    });
};

这是一个更新的 JavaScript 示例,使用 ES6 风格的代码和承诺,减去错误处理:

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

exports.handler = async (event, context) => {
  const Bucket = event.Records[0].s3.bucket.name;
  const Key = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, ' '));
  const data = await s3.getObject({ Bucket, Key }).promise();
  console.log("Raw text:\n" + data.Body.toString('ascii'));
};

许多张贴者要求使用 Java 中的等价物,所以这里有一个例子:

package example;

import java.net.URLDecoder;

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.S3Event;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.event.S3EventNotification.S3EventNotificationRecord;

public class S3GetTextBody implements RequestHandler<S3Event, String> {
 
    public String handleRequest(S3Event s3event, Context context) {
        try {
            S3EventNotificationRecord record = s3event.getRecords().get(0);

            // Retrieve the bucket & key for the uploaded S3 object that
            // caused this Lambda function to be triggered
            String bkt = record.getS3().getBucket().getName();
            String key = record.getS3().getObject().getKey().replace('+', ' ');
            key = URLDecoder.decode(key, "UTF-8");

            // Read the source file as text
            AmazonS3 s3Client = new AmazonS3Client();
            String body = s3Client.getObjectAsString(bkt, key);
            System.out.println("Body: " + body);
            return "ok";
        } catch (Exception e) {
            System.err.println("Exception: " + e);
            return "error";
        }
    }
}
于 2015-06-04T23:13:03.243 回答
15

您可以使用data.Body.toString('ascii')来获取文本文件的内容,假设文本文件被编码为使用 ascii 格式。您还可以将其他编码类型传递给该函数。查看节点缓冲区以获取更多详细信息。

于 2015-11-12T13:50:01.403 回答
14

我在 python 3.6 环境中使用 lambda 函数。下面的代码将读取存储桶 my_s3_bucket 中文件 main.txt 的内容。确保根据您的需要替换存储桶的名称和文件名。

def lambda_handler(event, context):
    # TODO implement
    import boto3

    s3 = boto3.client('s3')
    data = s3.get_object(Bucket='my_s3_bucket', Key='main.txt')
    contents = data['Body'].read()
    print(contents)
于 2018-07-27T13:25:54.303 回答