S3 Bucket中Lambda复制重命名文件报错:无效存储桶名称
解决S3复制文件时的「无效存储桶名称」错误
问题场景
我正在编写Lambda函数测试Athena表,功能已正常运行。现在需要重命名ResultConfiguration生成的输出文件,由于S3无法直接重命名,打算通过复制后删除原文件实现,但执行时一直提示「无效存储桶名称」错误。
相关代码
def copy_delete_output_results(query_id, table_name): oldCsvFileLocation = output + query_id + '.csv' newOutputLocation = output + table_name newFileName = table_name + '.csv' s3.Object(newOutputLocation,newFileName).copy_from(CopySource=oldCsvFileLocation) s3.Object(output,oldCsvFileLocation).delete() # 变量示例 oldCsvFileLocation = 's3://ab-binaries-bucket-devtest/test/testQueryResults/1d8ab6ce-eda0-435f-93c3-2baa6fec8abd.csv' newOutputLocation = 's3://ab-binaries-bucket-devtest/test/testQueryResults/dsm_abc_dns' newFileName = 'dsm_abc_dns.csv'
报错信息
无效存储桶名称 "s3://ab-binaries-bucket-devtest/test/testQueryResults/dsm_abc_dns":存储桶名称必须匹配正则表达式 "^[a-zA-Z0-9.-_]{1,255}$",或者匹配ARN格式的正则表达式 "arn:(aws).*:(s3|s3-object-lambda):[a-z-0-9]*:[0-9]{12}:accesspoint[/:][a-zA-Z0-9-.]{1,63}$|arn:(aws).*:s3-outposts:[a-z-0-9]+:[0-9]{12}:outpost[/:][a-zA-Z0-9-]{1,63}[/:]accesspoint[/:][a-zA-Z0-9-]{1,63}$"
问题原因
核心错误是boto3的s3.Object()参数使用错误:
s3.Object()的第一个参数要求是纯存储桶名称(比如ab-binaries-bucket-devtest),第二个参数是文件的完整键(桶内路径+文件名)- 你传入的是完整的S3路径(包含
s3://前缀和桶内子路径),导致boto3把整个路径当成了桶名,自然不符合桶名的正则规则 - 另外,
copy_from的参数格式也需要注意,虽然支持字符串格式,但要确保路径拆分正确
修正后的代码
方式1:直接指定桶名和基础路径
def copy_delete_output_results(query_id, table_name): # 明确指定存储桶名称和桶内基础路径 bucket_name = 'ab-binaries-bucket-devtest' base_key = 'test/testQueryResults/' # 构建原文件和新文件的完整键 old_file_key = base_key + query_id + '.csv' new_file_key = base_key + table_name + '.csv' # 复制文件:第一个参数是桶名,第二个是新文件的键 s3.Object(bucket_name, new_file_key).copy_from( CopySource={'Bucket': bucket_name, 'Key': old_file_key} ) # 删除原文件 s3.Object(bucket_name, old_file_key).delete()
方式2:自动拆分完整S3路径(更灵活)
如果output变量是完整的s3://ab-binaries-bucket-devtest/test/testQueryResults/,可以通过字符串处理自动拆分桶名和路径:
def copy_delete_output_results(query_id, table_name): # 拆分S3路径,提取桶名和基础路径 output_clean = output.strip().replace('s3://', '') bucket_name, base_key = output_clean.split('/', 1) if '/' in output_clean else (output_clean, '') # 确保基础路径末尾带斜杠,避免拼接时出错 if base_key and not base_key.endswith('/'): base_key += '/' old_file_key = base_key + query_id + '.csv' new_file_key = base_key + table_name + '.csv' # 使用字符串格式的CopySource也可以 s3.Object(bucket_name, new_file_key).copy_from( CopySource=f's3://{bucket_name}/{old_file_key}' ) s3.Object(bucket_name, old_file_key).delete()
关键注意点
- 永远不要把完整的S3 URL传给
s3.Object()的第一个参数,必须单独传入纯桶名 CopySource支持两种格式:字典格式{'Bucket': '桶名', 'Key': '文件键'}(更清晰),或者字符串格式s3://桶名/文件键- 处理路径时注意末尾的斜杠,避免拼接后出现
test/testQueryResults//xxx.csv这类无效路径
内容的提问来源于stack exchange,提问作者na2193
相关产品推荐
相关产品推荐

