You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何不用本地下载S3桶内文件,用boto3打包为zip后传回原桶

实现方案

完全可以通过内存流实现全程不落地本地文件,无需先下载对象到本地磁盘即可完成打包上传。

核心逻辑

借助Python内置的io.BytesIO作为中间缓存载体:

  1. 拉取S3对象内容直接写入内存中的压缩包流
  2. 所有对象打包完成后,直接将内存中的压缩包流上传回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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 13:45:02