如何获取单个S3文件创建事件?多客户端上传多事件问题
嘿,这个问题我之前帮好几个开发者处理过,咱们先拆解下为什么会出现这种情况,再给你靠谱的解决办法:
为什么会触发多个ObjectCreated事件?
这种情况大多是因为你用的SFTP(或其他上传客户端)的上传逻辑导致的:很多客户端会先创建一个0字节的占位文件(用来锁定上传路径,避免冲突),然后再逐步写入文件内容,最后可能通过重命名或二次写入完成上传流程。这就会让S3连续触发多次对象创建事件:
- 第一次是创建占位文件的
ObjectCreated:Put(大小为0) - 后面两次通常是文件内容写入完成后的
ObjectCreated:Put,或者如果客户端用了重命名操作,可能会触发ObjectCreated:Copy+ObjectCreated:Put(具体取决于客户端实现)
怎么过滤无效的0字节事件,只获取真正的文件完成通知?
给你三个可行的方案,按推荐程度排序:
方案1:在S3事件通知里直接过滤(最省资源,优先用)
S3本身支持在事件配置里添加对象大小过滤条件,直接把0字节的事件拦在源头:
- 打开S3控制台,进入目标存储桶的「属性」→「事件通知」
- 编辑已有的通知规则(或者新建规则)
- 在「事件类型」里勾选你需要的
ObjectCreated相关类型(比如Put、Copy、CompleteMultipartUpload) - 找到「高级条件」板块,添加对象大小大于0字节的过滤规则:
- 选择「对象大小」→「大于」→ 输入
0
- 选择「对象大小」→「大于」→ 输入
- 保存规则即可
这样S3只会把大小>0的对象创建事件推送到你的SNS主题,直接跳过那些占位的0字节文件事件。
方案2:在SNS消息的消费端处理
如果因为权限或其他限制没法修改S3的事件配置,那可以在消费SNS消息的代码里做过滤:
- 解析SNS消息中的S3事件内容,提取
object.size字段 - 只处理
size > 0的消息,直接忽略0字节的占位文件
给你一段Python伪代码参考:
import json def handle_sns_message(sns_message): # 解析SNS外层消息 sns_payload = json.loads(sns_message) # 解析内部的S3事件内容 s3_event_data = json.loads(sns_payload['Message']) for record in s3_event_data['Records']: object_key = record['s3']['object']['key'] object_size = int(record['s3']['object']['size']) if object_size > 0: # 这里写你处理有效文件的逻辑 print(f"开始处理新文件: {object_key},大小: {object_size}字节") else: # 跳过0字节的占位文件 print(f"忽略0字节占位文件: {object_key}")
方案3:用Lambda做中间层统一过滤
如果你的多个存储桶都有这个需求,或者SNS后面还要对接其他服务,你可以加一个Lambda函数作为中间层:
- 把S3的事件通知目标改成这个Lambda函数,而不是直接推SNS
- 在Lambda里过滤掉所有0字节的对象事件
- 只把符合条件的有效事件推送到你的SNS主题
这样可以统一处理所有存储桶的过滤逻辑,不用逐个桶修改配置,扩展性更强。
额外小提示
如果有些客户端用了S3的分块上传功能,那文件上传完成时会触发ObjectCreated:CompleteMultipartUpload事件,这个事件对应的肯定是完整的文件。你可以在S3事件配置里单独勾选这个事件类型,再结合大小过滤,能更精准地捕获完整的上传完成事件。
内容的提问来源于stack exchange,提问作者Kyle Heuton
相关产品推荐
相关产品推荐

