使用Python在S3上从S3文件创建zip文件

8

我尝试将位于S3存储桶中的目录中保持相同目录结构的所有文件压缩,并将该zip文件放置在S3存储桶上。

使用BytesIO和zipfile从S3存储桶解压缩zip文件很容易,但我不确定如何处理包含数百个文件的目录。

我发现这篇链接对我有帮助,但是它是针对Lambda Node的文章。 创建一个在S3上基于文件创建zip文件

1个回答

2
为了避免将各个对象下载到磁盘上,您需要流式传输每个前缀的对象(请记住:S3使用层次结构),将其保存在本地压缩包中,上传到S3,然后删除。这里是我会使用的代码(并且已经在AWS上成功测试):
import boto3
import io
import zipfile
import os

s3 = boto3.client('s3')

def zip_files(bucket_name, prefix):
    # List all objects in the bucket with the specified prefix
    response = s3.list_objects_v2(Bucket=bucket_name, Prefix=prefix)


    # Create a BytesIO object to store the compressed data
    zip_buffer = io.BytesIO()

    for obj in response.get('Contents', []):
        s3_object = s3.get_object(Bucket=bucket_name, Key=obj['Key'])

        # Use the ZipFile module to write the contents of the S3 object to the zip stream
        with zipfile.ZipFile(zip_buffer, 'w') as zip_file:
            # Write the contents of the S3 object to the zip file
            zip_file.writestr(obj['Key'], s3_object['Body'].read())

        # Save the zip file to disk
        with open(f'{prefix.rstrip("/")}.zip', 'wb') as f:
            f.write(zip_buffer.getvalue())

    # Upload the compressed data to the S3 bucket and delete
    zip_buffer.seek(0)
    s3.put_object(Bucket=bucket_name, Key=f'{prefix}{prefix.rstrip("/")}.zip', Body=zip_buffer)
    os.remove(f'{prefix.rstrip("/")}.zip')

bucket = 'foobucket'
folders = ['foo/', 'bar/', 'baz/']
for folder in folders:
    zip_files(bucket, folder)

您还没有提供任何Python代码来显示您是否遇到了与您链接的Lambda Node中描述的相同的内存限制,因此我假设这不是一个巨大的问题。无论如何,os.remove应该使进程保持轻量级。

另外:如果您在Lambda函数内运行此逻辑,则必须调整它以适应Lambda所需的格式。

显然,根据您的需求添加日志记录和错误处理。

希望这可以帮助您!


压缩文件将覆盖现有内容。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接