如何不用本地下载S3桶内文件,用boto3打包为zip后传回原桶
实现方案
完全可以通过内存流实现全程不落地本地文件,无需先下载对象到本地磁盘即可完成打包上传。
核心逻辑
借助Python内置的io.BytesIO作为中间缓存载体:
- 拉取S3对象内容直接写入内存中的压缩包流
- 所有对象打包完成后,直接将内存中的压缩包流上传回S3
完整实现代码
import boto3 import io import zipfile def zip_s3_folder(bucket_name, source_folder_prefix, target_zip_key): s3 = boto3.resource('s3') bucket = s3.Bucket(bucket_name) zip_buffer = io.BytesIO() # 操作内存流写入压缩包 with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED, allowZip64=True) as zipf: # 遍历指定文件夹下的所有对象 for obj in bucket.objects.filter(Prefix=source_folder_prefix): # 跳过文件夹占位对象、以及目标压缩包本身(避免重复打包) if obj.key.endswith('/') or obj.key == target_zip_key: continue # 读取S3对象内容直接写入压缩包,不落地本地 obj_content = obj.get()['Body'].read() # 自定义压缩包内的文件路径,这里默认去掉源文件夹前缀,保留相对层级 inner_file_path = obj.key.replace(source_folder_prefix, '', 1) zipf.writestr(inner_file_path, obj_content) # 重置流指针到起始位置,否则上传内容为空 zip_buffer.seek(0) # 直接上传内存流到S3 bucket.upload_fileobj(zip_buffer, target_zip_key) return f"s3://{bucket_name}/{target_zip_key}" # 调用示例 if __name__ == "__main__": # 替换为你自己的配置 BUCKET = "your-bucket-name" SOURCE_FOLDER = "data/target-files/" # 要打包的文件夹前缀 TARGET_ZIP = "output/archive.zip" # 打包后存放到S3的对象键 uploaded_path = zip_s3_folder(BUCKET, SOURCE_FOLDER, TARGET_ZIP) print(f"压缩包上传完成:{uploaded_path}")
补充说明
allowZip64=True支持生成超过4GB的压缩包,总压缩大小小于4GB可移除该参数- 若单对象体积过大导致内存占用高,可修改为流式分段读取S3对象内容写入压缩包,进一步优化内存占用
- 不需要压缩仅需打包时,可将
zipfile.ZIP_DEFLATED替换为zipfile.ZIP_STORED,大幅提升打包速度 - 不需要保留文件夹层级时,可将
inner_file_path修改为obj.key.split('/')[-1],直接取文件名作为压缩包内路径
内容的提问来源于stack exchange,提问作者Sairam Ravuri
相关产品推荐
相关产品推荐

