如何使用boto3查找S3对象前缀并按文件名更新对象
问题描述
我有一个已填充内容的S3存储桶,需要按指定文件名搜索并更新对应对象。存储桶里有带前缀的现有对象列表,我需要递归遍历所有对象(包含所有前缀目录),匹配目标文件名后通过S3文件上传更新它。
举个例子,存储桶根目录及子前缀下的对象如下:
cat2.jpg cat3.jpg PRE CAT_PICS/cat.jpg PRE CAT_PICS/cat2.jpg PRE CAT_PICS/MORE_CAT_PICS/cat3.jpg
现在要递归搜索并更新所有cat3.jpg对象,请问该怎么实现?另外,能不能提取找到的对象的前缀?
我自己写了一段代码,但不确定是否正确,而且因为缺少分页处理,没法覆盖超过1000个对象的情况:
当前代码:
import boto3 FILE_TO_UPDATE = cat3.jpg s3_bucket = "example_bucket2182023" s3_client = boto3.client("s3") for my_bucket_object in my_bucket.objects.all(): if my_bucket_object.endswith(FILE_TO_UPDATE): try: s3_client.put_object( Bucket=s3_bucket, key=my_bucket_object ) except: print(f"Error uploading {my_bucket_object} to {s3_bucket}") print(my_bucket_object.key)
解决方案
1. 修复代码基础问题
你的现有代码存在几个明显错误:
FILE_TO_UPDATE未加引号,需定义为字符串:FILE_TO_UPDATE = "cat3.jpg"- 未初始化
my_bucket对象,需通过boto3资源类创建:s3_resource = boto3.resource("s3"); my_bucket = s3_resource.Bucket(s3_bucket) my_bucket_object是S3对象实例,需调用key属性才能做字符串匹配:my_bucket_object.key.endswith(FILE_TO_UPDATE)put_object需指定上传内容(比如本地文件的Body参数),且Key参数要传入对象完整键值
2. 处理分页(支持1000+对象)
使用boto3资源类的Bucket.objects.all()会自动处理S3的1000条分页限制,无需手动处理ContinuationToken,直接遍历即可覆盖所有对象。
3. 提取对象前缀
通过字符串处理即可提取前缀:
- 用
os.path.dirname(object_key):如果对象是CAT_PICS/MORE_CAT_PICS/cat3.jpg,会返回CAT_PICS/MORE_CAT_PICS;如果是根目录的cat3.jpg,会返回空字符串
完整代码示例
import boto3 import os # 配置参数 TARGET_FILENAME = "cat3.jpg" S3_BUCKET_NAME = "example_bucket2182023" LOCAL_FILE_PATH = "./cat3.jpg" # 本地要上传的目标文件路径 # 初始化S3资源和客户端 s3_resource = boto3.resource("s3") s3_client = boto3.client("s3") my_bucket = s3_resource.Bucket(S3_BUCKET_NAME) # 遍历所有对象(自动处理分页) for obj in my_bucket.objects.all(): object_key = obj.key # 精准匹配文件名(避免类似mycat3.jpg的误匹配) if os.path.basename(object_key) == TARGET_FILENAME: # 提取对象前缀 object_prefix = os.path.dirname(object_key) print(f"找到匹配对象:{object_key},前缀:{object_prefix}") try: # 上传本地文件覆盖S3对象 with open(LOCAL_FILE_PATH, "rb") as file: s3_client.put_object( Bucket=S3_BUCKET_NAME, Key=object_key, Body=file ) print(f"成功更新对象:{object_key}") except Exception as e: print(f"更新对象{object_key}失败:{str(e)}")
关键说明
- 用
os.path.basename()比endswith()更精准,避免文件名包含目标字符串的误匹配 - 资源类的遍历方法自动处理分页,无需额外代码
- 前缀提取逻辑兼容根目录和多级子目录的情况
内容的提问来源于stack exchange,提问作者asultan904
相关产品推荐
相关产品推荐

