如何在AWS S3存储桶间复制对象并解决Boto3 No Such Key错误
问题根源
- 代码中源桶和目标桶参数写反:
copy_object的Bucket参数是目标存储桶,CopySource对应的是源存储桶+源对象Key,你的代码里硬编码的桶名逻辑完全颠倒,而且没有用到函数传入的bucket_from_name参数 CopySource格式错误:官方推荐传入字典格式而非字符串,能自动处理Key中的特殊字符(包括空格、中文、特殊符号),避免手动编码导致的No Such Key错误- S3本身没有目录层级的概念:不需要提前创建
some_dynamic_folder,只要目标Key中包含路径前缀,S3会自动生成对应的逻辑目录,完全不需要额外的目录创建操作 - 直接用
split('/')取文件名会出错:如果img_url是带URL编码的路径,或者包含多级路径/特殊字符,拆分逻辑会失效
修正后的实现代码
import boto3 from urllib.parse import unquote S3 = boto3.client('s3') def copy_to_bucket(bucket_from_name, bucket_to_name, source_key, target_folder): try: # 解码源Key的URL编码,处理空格等特殊字符 source_key = unquote(source_key) # 提取源文件名 file_name = source_key.split('/')[-1] # 构造目标Key,自动带上文件夹前缀 target_key = f"{target_folder.rstrip('/')}/{file_name}" response = S3.copy_object( Bucket=bucket_to_name, # 目标存储桶 # 用字典格式传CopySource,自动处理特殊字符,无需手动编码 CopySource={ 'Bucket': bucket_from_name, 'Key': source_key }, Key=target_key ) return response except Exception as error: print(f"复制失败: {str(error)}") return None
调用示例
如果你需要把bucket1里的sample.jpg复制到bucket2的some_dynamic_folder下,调用方式如下:
copy_to_bucket( bucket_from_name='bucket1', bucket_to_name='bucket2', source_key='sample.jpg', target_folder='some_dynamic_folder' )
额外适配逻辑
如果你传入的是完整的S3访问URL(比如https://bucket1.s3.region.amazonaws.com/sample.jpg),可以新增URL拆分逻辑,不用手动传入源桶参数:
from urllib.parse import urlparse def parse_s3_url(s3_url): parsed = urlparse(s3_url) # 处理虚拟主机风格的S3 URL if '.s3.' in parsed.netloc: bucket = parsed.netloc.split('.s3.')[0] key = parsed.path.lstrip('/') # 处理路径风格的S3 URL else: bucket = parsed.path.split('/')[1] key = '/'.join(parsed.path.split('/')[2:]) return bucket, unquote(key)
注意事项
- 如果源对象的访问权限是私有,确保你使用的AK/SK同时拥有源桶的
s3:GetObject权限和目标桶的s3:PutObject权限 - 大于5GB的对象不要使用
copy_object,请改用分块复制的upload_part_copy接口
内容的提问来源于stack exchange,提问作者KcH
相关产品推荐
相关产品推荐

