gpt4 book ai didi

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

转载 作者:太空宇宙 更新时间:2023-11-04 05:12:06 25 4
gpt4 key购买 nike

使用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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com