如何使用boto上传到s3时进行gzip

Alf*_*lfe 12 python gzip amazon-s3 boto gzipfile

我有一个大的本地文件.我想使用该boto库将该文件的gzip压缩版本上传到S3 .该文件太大,无法在上载之前在磁盘上高效地进行gzip,因此在上传过程中应该以流式方式对其进行gzip压缩.

boto库知道一个函数set_contents_from_file(),它需要一个类似文件的对象.

gzip库知道GzipFile可以通过名为的参数获取对象的类fileobj; 它会在压缩时写入此对象.

我想结合这两个函数,但是一个API想要自己阅读,另一个API想要自己编写; 既不知道被动操作(如写入或被读取).

有没有人知道如何以工作方式结合这些?

编辑:我接受了一个答案(见下文),因为它暗示我要去哪里,但如果你有同样的问题,你可能会发现我自己的答案(也在下面)更有帮助,因为我实现了一个使用分段上传的解决方案.

Alf*_*lfe 24

我在garnaat接受的答案的评论中实施了暗示的解决方案:

import cStringIO
import gzip

def sendFileGz(bucket, key, fileName, suffix='.gz'):
    key += suffix
    mpu = bucket.initiate_multipart_upload(key)
    stream = cStringIO.StringIO()
    compressor = gzip.GzipFile(fileobj=stream, mode='w')

    def uploadPart(partCount=[0]):
        partCount[0] += 1
        stream.seek(0)
        mpu.upload_part_from_file(stream, partCount[0])
        stream.seek(0)
        stream.truncate()

    with file(fileName) as inputFile:
        while True:  # until EOF
            chunk = inputFile.read(8192)
            if not chunk:  # EOF?
                compressor.close()
                uploadPart()
                mpu.complete_upload()
                break
            compressor.write(chunk)
            if stream.tell() > 10<<20:  # min size for multipart upload is 5242880
                uploadPart()
Run Code Online (Sandbox Code Playgroud)

它似乎没有问题.毕竟,流媒体在大多数情况下只是数据的分块.在这种情况下,大块大约10MB,但谁在乎呢?只要我们不是在谈论几个GB块,我对此很好.


Python 3的更新:

from io import BytesIO
import gzip

def sendFileGz(bucket, key, fileName, suffix='.gz'):
    key += suffix
    mpu = bucket.initiate_multipart_upload(key)
    stream = BytesIO()
    compressor = gzip.GzipFile(fileobj=stream, mode='w')

    def uploadPart(partCount=[0]):
        partCount[0] += 1
        stream.seek(0)
        mpu.upload_part_from_file(stream, partCount[0])
        stream.seek(0)
        stream.truncate()

    with open(fileName, "rb") as inputFile:
        while True:  # until EOF
            chunk = inputFile.read(8192)
            if not chunk:  # EOF?
                compressor.close()
                uploadPart()
                mpu.complete_upload()
                break
            compressor.write(chunk)
            if stream.tell() > 10<<20:  # min size for multipart upload is 5242880
                uploadPart()
Run Code Online (Sandbox Code Playgroud)


Ren*_* B. 8

您还可以使用 gzip 轻松压缩字节并轻松上传如下:

import gzip
import boto3

cred = boto3.Session().get_credentials()

s3client = boto3.client('s3',
                            aws_access_key_id=cred.access_key,
                            aws_secret_access_key=cred.secret_key,
                            aws_session_token=cred.token
                            )

bucketname = 'my-bucket-name'      
key = 'filename.gz'  

s_in = b"Lots of content here"
gzip_object = gzip.compress(s_in)

s3client.put_object(Bucket=bucket, Body=gzip_object, Key=key)
Run Code Online (Sandbox Code Playgroud)

可以s_in用任何字节、io.BytesIO、pickle dumps、文件等替换。

如果你想上传压缩的 Json 那么这里是一个很好的例子:Upload compression Json to S3


gar*_*aat 5

实际上没有办法做到这一点,因为S3不支持真正的流输入(即分块传输编码).您必须在上传之前知道Content-Length,并且知道这是首先执行gzip操作的唯一方法.

  • 是的,S3支持分段上传.但是,在上传之前必须知道每个部分.S3中不支持流式上传.将您的巨大文件分成几部分并使用多部分声音就像一个合理的方法. (2认同)