当前位置: 首页 > 知识库问答 >
问题:

AWS Lambda put_对象函数未将文件发送到目标s3存储桶

岳浩宕
2023-03-14

我调用一个Lambda函数,将一个.csv文件从电子邮件发送到我在所述函数中指定的目标s3存储桶。当传入的s3 bucket接收到电子邮件时,调用由事件类型:ObjectCreatedByPut触发。

我从CloudWatch日志中看到该函数确实按预期调用,但从未将文件发送到目标s3存储桶。

这是显示键mfdat0psudj12qfihankjkiindd17vftd775so01存在的传入文件夹

这是Lambda函数;

from __future__ import print_function

import json
import urllib
import boto3
import os

import email
import base64

FILE_MIMETYPE = 'text/csv'

# destination folder
S3_OUTPUT_BUCKETNAME = 's3-bucket/attachments/' 

print('Loading function')

s3 = boto3.client('s3')


def lambda_handler(event, context):

    #source email bucket 
    inBucket = event['Records'][0]['s3']['bucket']['name']
    key = urllib.parse.quote(event['Records'][0]['s3']['object']['key'].encode('utf8'))


    try:
        response = s3.get_object(Bucket=inBucket, Key=key)
        msg = email.message_from_string(response['Body'].read().decode('utf-8'))   

    except Exception as e:
        print(e)
        print('Error retrieving object {} from source bucket {}. Verify existence and ensure bucket is in same region as function.'.format(key, inBucket))
        raise e
    
    #print(msg)
    
    attachment_list = []
    attachment = msg.get_payload()[1]


    try:
        #scan each part of email 
        for message in msg.get_payload():
            
            # Check filename and email MIME type
            if (message.get_filename() != None and message.content_type() == FILE_MIMETYPE):
                attachment_list.append ({'original_msg_key':key, 'attachment_filename':message.get_filename(), 'body': base64.b64decode(msg.get_payload()) })
    except Exception as e:
        print(e)
        print ('Error processing email for CSV attachments')
        raise e
    
    # if multiple attachments send all to bucket 
    for attachment in attachment_list:

        try:
            s3.put_object(Bucket=S3_OUTPUT_BUCKETNAME, Key=attachment['original_msg_key'] +'-'+attachment['attachment_filename'] , Body=attachment['body']) 
        except Exception as e:
            print(e)
            print ('Error sending object {} to destination bucket {}. Verify existence and ensure bucket is in same region as function.'.format(attachment['attachment_filename'], S3_OUTPUT_BUCKETNAME))
            raise e
            
    print(key)
    print(inBucket)
    print(S3_OUTPUT_BUCKETNAME)
    print(message.get_filename())
    print(response)

    return event

这里是显示函数成功调用的日志。

Timestamp
Message
No older events at this moment. 
Retry

2020-10-25T22:05:32.093+00:00   Loading function

2020-10-25T22:05:32.208+00:00   START RequestId: 9d683660-4436-4cff-92c4-01e3ae028a67 Version: $LATEST

2020-10-25T22:05:33.326+00:00   mfdat0psudj12qfihankjkiindd17vftd775so01

2020-10-25T22:05:33.326+00:00   s3-bucket

2020-10-25T22:05:33.326+00:00   s3-bucket/attachments/

2020-10-25T22:05:33.326+00:00   None

2020-10-25T22:05:33.364+00:00   {'ResponseMetadata': {'RequestId': '4DCD1196A2C991B8', 'HostId': 'tKOE8xz3yq1gryGS+7f7u9+fdwU+buK4C/gTTzOZYZheSxXI9a1MxrggIioWttO9mwmCiwG15d0=', 'HTTPStatusCode': 200, 'HTTPHeaders': {'x-amz-id-2': 'tKOE8xz3yq1gryGS+7f7u9+fdwU+buK4C/gTTzOZYZheSxXI9a1MxrggIioWttO9mwmCiwG15d0=', 'x-amz-request-id': '4DCD1196A2C991B8', 'date': 'Sun, 25 Oct 2020 22:05:33 GMT', 'last-modified': 'Sun, 25 Oct 2020 22:05:31 GMT', 'etag': '"b66db710202d45a98daa0a47badf6094"', 'accept-ranges': 'bytes', 'content-type': 'application/octet-stream', 'content-length': '1207346', 'server': 'AmazonS3'}, 'RetryAttempts': 0}, 'AcceptRanges': 'bytes', 'LastModified': datetime.datetime(2020, 10, 25, 22, 5, 31, tzinfo=tzutc()), 'ContentLength': 1207346, 'ETag': '"b66db710202d45a98daa0a47badf6094"', 'ContentType': 'application/octet-stream', 'Metadata': {}, 'Body': <botocore.response.StreamingBody object at 0x7ffba103f490>}

2020-10-25T22:05:33.366+00:00   END RequestId: 9d683660-4436-4cff-92c4-01e3ae028a67

2020-10-25T22:05:33.366+00:00   REPORT RequestId: 9d683660-4436-4cff-92c4-01e3ae028a67 Duration: 1157.42 ms Billed Duration: 1200 ms Memory Size: 128 MB Max Memory Used: 89 MB Init Duration: 413.53 ms
No newer events at this moment. 
Auto retry paused.
 
Resume

然而,当我检查s3 bucket/attachments时,目录是空的。有趣的是,打印(message.get\u filename())返回无。

我已经检查了Lambda代码的错误,并尝试使用s3。上传文件,但这似乎也不起作用。

不知道现在该转向哪里。

共有3个答案

孟新知
2023-03-14

在改进了错误处理并探索了邮件库的方法之后,我能够确认这条消息。content\u type()不正确,正确的方法是infact消息。获取content\u type()。使用错误方法的含义是,msg.get\u payload()中消息的条件:…无法计算和输出任何内容,因此为打印(message.get\u filename())返回了,因此为附件列表返回了空白列表。

下面的正确语句供任何希望使用Lambda或其他地方复制此功能的人参考。

try:
        #scan each part of email 
        for message in msg.get_payload():
            
            # Check filename and email MIME type
            if  (message.get_content_type() == FILE_MIMETYPE and message.get_filename() != None):
                attachment_list.append ({'original_msg_key':key, 'attachment_filename':message.get_filename(), 'body': base64.b64decode(message.get_payload()) })
    except Exception as e:
        print(e)
        print ('Error processing email for CSV attachments')
        raise e

感谢所有的贡献和指导。

龚招
2023-03-14

您的打印(message.get\u filename())似乎表明文件名为“无”,并且您的循环中有一个特定的大小写,表示消息。get\u filename()!=没有,所以看起来没有有效的附件。

我将围绕负载中的消息添加更多调试,然后仔细检查您对有效文件名、mimetype等的假设,以及您是否具有正确的条件设置。

翁文康
2023-03-14

您正在设置S3\u OUTPUT\u BUCKETNAME='S3 bucket/attachments/',并将其用作调用put\u对象中bucket的参数。这行不通,因为bucket名称不能包含斜杠(/)。

“文件夹”必须是键的一部分。事实上,S3没有任何文件夹,因为它不是文件系统。来自实际文件系统的文件夹被翻译成前缀作为对象键的一部分。

尝试按以下方式更改功能:

...
S3_OUTPUT_BUCKETNAME = 's3-bucket'
...
s3.put_object(
    Bucket=S3_OUTPUT_BUCKETNAME, 
    Key='attachments/' + attachment['original_msg_key'] + '-' + attachment['attachment_filename'] , 
    Body=attachment['body']
)
...

话虽如此,我怀疑附件列表是空的,甚至没有执行。请在应该向列表添加附件的if语句和迭代附件列表中项目的for循环周围添加一些日志。那里可能隐藏着一个bug。

 类似资料:
  • 有没有一种方法可以将文件列表从一个S3存储桶复制到另一个存储桶?两个S3存储桶都在同一个AWS帐户中。我可以使用aws cli命令一次复制一个文件: 然而,我有1000份文件要复制。我不想复制源存储桶中的所有文件,因此无法使用sync命令。有没有一种方法可以用需要复制的文件名列表来调用一个文件,从而自动化这个过程?

  • 问题内容: 我目前利用以下内容将文件上传到S3: 上面的方法工作正常,但我想直接将a保存到S3以从应用程序中删除几秒钟,但是我不知道如何执行此操作?这是我当前将图像保存到文件中的方式: 有没有一种方法可以直接以流的形式直接写入Amazon S3,如果可以,有人可以显示示例吗? 另外,这是个好主意吗?如果它容易出错,我将继续使用当前方法。任何建议表示赞赏。 问题答案: 以下(或类似的东西)应该可以正

  • 我正在寻找一种方法来传输任何文件类型的原始文件数据和任何可能的内容(我的意思是文件和文件内容都是用户生成的),在主干前端使用xhr/ajax调用,在Django后端使用这两种方法。 编辑:也许这个问题还不清楚... 如果在IDE中打开一个文件(如Sublime),则可以查看和编辑组成该文件的实际代码。我试图将原始内容放入JSON中,这样我就可以发送到浏览器,修改后再发送回去。 我发布这个问题是因为

  • 我使用数据砖在R中开发了一个模型。我想将输出数据文件保存在 AWS S3 存储桶上,但当我保存文件如下时,它不会保存到挂载的驱动器。 使用R将数据挂载到S3的最佳方法是什么? 我已经尝试了下面的示例代码,它可以工作,所以我知道我在AWS和Database ricks之间的连接可以工作。

  • 问题内容: 我不知道这是否可能,但是可以。使用回调使工作变得更加困难。 我有一个包含html文件的目录,我想使用node.js和socket.io将它们以对象块的形式发送回客户端。 我所有的文件都在/ tmpl中 因此,套接字需要读取/ tmpl中的所有文件。 对于每个文件,必须将数据存储在对象中,文件名作为键,内容作为值。 最后的回调也是错误的。目录中的所有文件完成后,必须调用它。 但是我不知道

  • 问题内容: 我正在尝试使用适用于AWS的新boto3客户端做一个“ hello world” 。 我的用例非常简单:从S3获取对象并将其保存到文件中。 在boto 2.XI中,它应该是这样的: 在boto 3中。我找不到一种干净的方法来做同样的事情,所以我手动遍历了“ Streaming”对象: 要么 而且效果很好。我想知道是否有任何“本机” boto3函数可以完成相同的任务? 问题答案: Bot