S3→SNS→SQS触发Lambda链路中如何传递上传图片的对象Key
S3→SNS→SQS→Lambda 链路中S3对象Key传递实现
核心传递逻辑
- 根本不需要额外开发代码手动传递S3 Key,AWS原生的消息透传机制会把Key跟着消息流一路传到Lambda:
- S3推送事件通知时,会在标准事件结构里内置
bucket.name和object.key字段,直接记录本次触发对应的存储桶和对象路径 - SNS接收S3通知时默认透传完整的原始事件内容,只是在最外层套一层SNS自己的消息信封(包含TopicArn、MessageId这类元数据),不会裁剪原始事件里的字段
- SQS接收到SNS投递的消息时,同样完整透传SNS的消息内容,不会修改内部的嵌套结构
- Lambda被SQS触发时,会把从SQS拉到的所有消息作为event入参传进函数,只要按照消息的嵌套层级逐层解析,就能拿到对应的S3对象Key
- S3推送事件通知时,会在标准事件结构里内置
Lambda端解析示例
Lambda从SQS拿到的event是三层嵌套结构,得逐层反序列化才能定位到Key的位置:
- 最外层是SQS批量拉取的消息列表,所有消息都存在于
event.Records字段里 - 每条SQS消息的
body字段是序列化后的SNS消息内容,第一步要先做JSON反序列化 - 反序列化后的SNS消息里,
Message字段就是最开始S3推过来的原始事件内容,得再做一次JSON反序列化
参考Python实现代码:
import json import urllib.parse def lambda_handler(event, context): for sqs_record in event.get("Records", []): # 解析SNS层消息 sns_content = json.loads(sqs_record["body"]) # 解析S3层原始事件 s3_origin_event = json.loads(sns_content["Message"]) for s3_record in s3_origin_event.get("Records", []): bucket = s3_record["s3"]["bucket"]["name"] # S3 Key本身是URL编码格式,必须解码还原真实对象路径 object_key = urllib.parse.unquote_plus(s3_record["s3"]["object"]["key"]) # 拿到Key后直接可以传给Rekognition接口处理对应图片 print(f"待处理图片定位:Bucket={bucket}, Key={object_key}")
常见配置注意事项
- 如果在SNS环节开了自定义消息转换、消息过滤规则,一定要检查配置逻辑有没有保留原始S3事件里的
Records.s3.object.key字段,别把消息裁剪了导致Key丢了 - 如果觉得三层嵌套的JSON解析太麻烦,可以在SNS配置环节把S3 Key单独提取成独立的消息属性,SQS默认会把SNS的消息属性透传给Lambda,直接从消息属性里读Key就行,不用逐层扒JSON
- 注意S3事件里的原始Key是URL编码格式,碰到用中文、空格、特殊字符命名的图片时,必须先做URL解码再调S3、Rekognition的接口,不然会报对象找不到的错误
- SQS触发Lambda默认是支持批量拉消息的,单批次最多能拉10条,循环里逐批解析处理所有上传的图片就行,没必要特意配置成单条消息触发
内容的提问来源于stack exchange,提问作者pratikdevops
相关产品推荐
相关产品推荐

