如何使用事件触发的Lambda从S3存储桶中获取最新的文件名或文件

12

我对AWS服务非常陌生,只有一周的无服务器架构经验。我的需求是在特定存储桶(bucket)上传新文件时触发事件,一旦事件触发,我的Lambda函数应该获取最新文件的详细信息,例如名称、大小和创建日期。

源将文件每次上传到一个新文件夹中,并使用当前日期命名文件夹。

到目前为止,我已经能够创建我的Lambda函数并监听事件触发。

以下是我的代码。

import boto3
import botocore
import datetime
import logging

def lambda_handler(event, context):
    logging.info('Start function')
    s3 = boto3.resource('s3')
    DATE = datetime.datetime.today().strftime('%Y-%m-%d')
    BUCKET_NAME = 'monkey-banana-dev'
    KEY = '/banana/incoming/daily/{}'.format(DATE)
    logging.info('Getting file from {}'.format(KEY))
    try:
        s3.Bucket(BUCKET_NAME).download_file(KEY, 'name_of_my_file')
    except botocore.exceptions.ClientError as e:
        if e.response['Error']['Code'] == "404":
            print("The object does not exist.")
        else:
            raise

我知道今天的日期,因此使用datetime来获取确切的KEY,但文件名将始终不同。虽然我知道它将是一个带有.txt后缀的文本文件,但我无法解决如何从触发器中获取最新上传文件的名称和其他细节。


1
您可以在此处找到有关事件的示例数据:http://docs.aws.amazon.com/lambda/latest/dg/eventsources.html#eventsources-s3-put - T4rk1n
@T4rk1n,我觉得它对我并没有太大的帮助,因为我对AWS非常陌生。 - Shek
3个回答

9
你有一个事件对象,它包含一个名为“Records”的列表。
你可以过滤eventName为'ObjectCreated:Put'的记录,然后按键“eventTime”对列表进行排序以获取最新的事件数据。
def lambda_handler(event, context):
    records = [x for x in event.get('Records', []) if x.get('eventName') == 'ObjectCreated:Put']
    sorted_events = sorted(records, key=lambda e: e.get('eventTime'))
    latest_event = sorted_events[-1] if sorted_events else {}
    info = latest_event.get('s3', {})
    file_key = info.get('object', {}).get('key')
    bucket_name = info.get('bucket', {}).get('name')

3
不应该需要排序。每个通知只应有一个记录。之所以表达为数组,是因为这是跨多个AWS服务使用的标准化消息格式。 - Michael - sqlbot
1
它包含整个文件路径还是只有文件名? - cedzz
有没有一种方法可以在运行Python脚本的ECS任务中获取文件名? - user812142

2
正如所提到的,此链接包含信息 - http://docs.aws.amazon.com/lambda/latest/dg/eventsources.html#eventsources-s3-put 您需要做的是利用传递到函数中的事件对象。该对象包含在链接中提供的详细信息。正如您在链接示例中看到的那样,您需要访问。这将包含完整路径,包括您提到的日期,因为键是完整文件路径。
为了帮助调试,您可以使用Python中的print函数将事件值打印到控制台。

1
有关使用S3事件的示例代码,请参见演练示例上的Python示例。 - John Rotenstein

2
"Key"将包含整个文件路径。 例如-
import boto3
import os
s3 = boto3.resource('s3')
bucket=s3.Bucket('hcss-heavyjob-raw-tables')
for key in bucket.objects.all():
    if key.key.startswith('heavyjob/EMPMAST'):
           print(key.key)'

输出-

heavyjob/EMPMAST/20190524-165352044.csv

heavyjob/EMPMAST/20190529-153011532.csv

heavyjob/EMPMAST/LOAD00000001.csv

您可以使用basename命令获取key.key的文件名或

head,tail = os.path.split(key.key)
print(tail)

1
请问您能否详细阐述答案,如果可能的话,附上一个例子? - Supratim Haldar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接