python - Boto3 下载 gzip 并作为流上传

标签 python amazon-s3 lambda boto3

使用python模块boto3,我再说一遍,使用boto3,而不是boto。如何从 S3 下载文件、gzip 并重新上传到 S3,而无需将文件写入磁盘?

我正在尝试编写一个 AWS lambda 函数,用于对上传到 S3 的所有内容进行 Gzip 压缩。问题是 lambda 函数被限制为 512MB 的磁盘空间,而我的上传可能远远超过这个。

我的假设是可以使用流来做到这一点,任何帮助将不胜感激!谢谢。

[更新]

下面的代码可以正常工作。它会将 block 上传到 S3,我可以看到生成的 *.gz 文件。但是,gzip header 未正确添加。在 mac 上打开文件会导致 Error 32 - Broken Pipe

有趣的是,如果文件大小小于 CHUNK_SIZE,即只有一次迭代,则文件已上传且未损坏。

有没有看到我做错了什么?

CHUNK_SIZE = 10000000
gz_buffer = io.BytesIO()
gz_stream = gzip.GzipFile(fileobj=gz_buffer, mode='wb', compresslevel=9)
obj = resource.Object(bucket, key)
body = obj.get()['Body']
try:
    while True:
        data = body.read(CHUNK_SIZE)
        if data:
            compressed_bytes = gz_stream.write(data)
            if compressed_bytes < CHUNK_SIZE:
                gz_stream.close()
            cdata = gz_buffer.getvalue()[0:compressed_bytes]
            # Upload cdata as multipart upload
            # This is a little helper function that 
            # uses boto3 create_multipart_upload
            multipart.upload(cdata)
        else:
            # Signal to S3 complete multipart upload
            multipart.complete()
            break
except Exception as e:
    pass

最佳答案

我会这样做:

import gzip,io

out_buffer = io.BytesIO()
f = gzip.open(out_buffer,"wb")

obj = resource.Object(bucket, key)
body = obj.get()['Body']
while True:
    read = body.read(500000)
    print('reading...')
    if read:
        # 1.) Stream chunks to gzip
        f.seek(0)
        nb_bytes = f.write(read)
        # 2.) Stream compressed chunks back to S3
        cdata = out_buffer.getvalue()[0:nb_bytes]
        # cdata now holds the compressed chunk of data
    else:
        break
  • 使用io.BytesIO在内存中创建一个“假”文件
  • 在其上映射一个 gzip 句柄
  • 循环读取(你的代码)
  • 在写入之前寻求假文件句柄的开始,这样它就不会使用太多内存(当前写入覆盖之前的迭代写入)
  • 将读取的数据写入 gzip 句柄,记下写入的字节数(它们根据数据而有所不同,如果它比上一次迭代更短,则 out_buffer 不会缩小,所以我们必须知道长度
  • 使用此长度对缓冲区的内容进行切片以创建压缩 block 。

请注意,在 python 2.x 中,您不能将文件对象传递给 gzip.open,您必须创建一个 Gzip 对象,如下所示:

f = gzip.GzipFile("foo.gz","wb",fileobj=out_buffer)

关于python - Boto3 下载 gzip 并作为流上传,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42726885/

相关文章:

java - 上传到 Amazon S3 时命名文件

python - 允许用户下载在 AWS 上生成的 zip 文件

c++ - 如何使用 lambda,返回一个 bool 作为参数

python - 初学者 python : monty hall & counter output

python - Pandas GroupBy 具有特殊总和

python - 如何从两个制表符分隔的文件中获取枢轴线?

java - 在java中计算S3对象(文件夹)的大小

java - 如何将字符串列表转换为 LinkedHashMap?

java - 使用 vavr 中的索引遍历列表

python - Pandas 读取科学记数法并改变