上传并压缩文件到S3

20
我最近开始使用S3,并遇到了上传和压缩大文件(10 GB +)到S3的需求。 我目前的实现方式是在本地创建一个临时压缩文件,然后将其上传到S3,最后删除临时文件。对于一个10 GB的文件,上传完成之前我本地存储了将近20 GB的空间。我需要一种方法将文件传输到S3,然后在那里进行压缩。 这种方法可行吗?如果是,我应该如何处理?如果不是,有没有办法减少本地所需的空间? 我看到有人建议将文件上传到S3,然后下载到同一区域的EC2中,在那里进行压缩,然后再将其上传回S3并删除S3上的第一个副本。这可能有效,但从成本的角度来看,两次上传获取一个文件似乎并不划算。 我尝试过上传压缩流,但没有成功,现在我对接下来该怎么做感到困惑。 我正在使用.NET上的gzip库。
5个回答

25
在Linux shell中,通过aws-cli,在您提出问题约3个月后,已添加了以下内容 :-) 已添加使用cp流式传输数据的功能 所以我想你能做的最好的就是将gzip的输出管道到aws cli:
从标准输入上传: gzip -c big_file | aws s3 cp - s3://bucket/folder/big_file.gz 下载到标准输出: aws s3 cp s3://bucket/folder/big_file.gz - | gunzip -c ...

非常有帮助。 - Jimmy Obonyo Abor
4
同样地,我们可以使用zip命令,并将“-”作为.zip文件名来创建一个流:zip - big_file | aws s3 cp - s3://bucket/folder/big_file.zip - freethebees
你好,有没有使用s3cmdtar来完成这个操作的方法? - Marry Jane

6

如果您最初存放文件的位置空间有限,那么将文件上传到S3,并随后在与S3桶位于同一地区的EC2实例上下载、压缩和重新上传文件到S3,实际上是一个非常明智的(尽管看似违反直觉的)建议,因为有一个简单的原因:

AWS 不会向您收取在同一区域内的EC2和S3之间的带宽费用

这是spot instance的理想工作...也是SQS告诉spot机器需要完成什么任务的一个很好的用例。

另一方面...如果您在上传之前不先压缩文件,则会消耗更多本地带宽。

如果您是程序员,应该能够编写类似我编写的实用程序供内部使用(这不是广告;目前不可发布),该实用程序可以通过外部工具压缩并实时上传文件到S3。

它的工作方式类似于此伪代码示例命令行:

cat input_file | gzip -9c | stream-to-s3 --bucket 'the-bucket' --key 'the/path'

那只是一个简化的使用示例,以说明概念。当然,我的“stream-to-s3”实用程序接受许多其他参数,包括x-amz-meta元数据、aws访问密钥和秘密,但你可能已经有了想法。
像gzip、pigz、bzip2、pbzip2、xz和pixz这样的常见压缩工具都可以从STDIN读取源文件,并将压缩数据写入STDOUT,而不必将文件的压缩版本写入磁盘。
我使用的实用程序通过管道从其STDIN读取文件数据,并使用S3 Multipart上传(即使对于不需要它的小文件,因为S3 Multipart Upload聪明地不需要您提前知道文件的大小),它只需将数据发送到S3,直到在其输入流上达到EOF。然后它完成多部分上传并确保一切都成功了。
我使用此实用程序构建和上传整个tarball,带有压缩,而不必触碰单个磁盘空间块。再次强调,编写它并不特别困难,可以使用多种语言完成。我甚至没有使用任何S3 SDK,而是从头开始自己编写了一个,使用标准的HTTP用户代理和S3 API文档。

OP说:“S3不支持压缩流。”我不确定这真正意味着什么,但我知道我的答案不是理论上的。我每天都会实时地向S3流式传输数十GB的高度压缩数据。S3通过多部分上传有效地支持了“流式传输”,并且对于正在上传的内容的压缩性质是不可知的。 - Michael - sqlbot
我的意思是上传时无法压缩它。已经压缩的文件可以正常上传。 所以,如果我理解正确,您的代码实际上成功读取了文件流,对其进行了压缩,并使用多部分上传(我熟悉此函数),而没有使用临时文件? - VmLino
我明白了。那就是我的做法,上传一个压缩文件,但是我是在从管道中获取已经被压缩的数据后进行上传的。 - Michael - sqlbot
一个分段上传只会在S3中创建一个文件(对象),所以如果你最终得到了3个文件,那就是你实现的缺陷,而不是你尝试的一般原则的缺陷。 - Michael - sqlbot
那么,如果我的多部分函数在外部方法中,并且我在循环中调用它,将其提供给一个流,其中包含压缩的原始文件的部分,为了使其工作,我想在每次调用时都将响应ID作为参数提供给它?在被告知这不起作用之前,这将是我的下一个尝试。 - VmLino
显示剩余2条评论

2
我需要一种将文件传输到S3并在那里进行压缩的方法。这种方法不可行/不可选。压缩需要大量的CPU资源,而Amazon S3专注于存储数据,而不是对您的文件进行重度处理。使用S3时,您还要为上传的内容付带宽费用,因此发送更多的数据会浪费金钱。
我看到有人建议将文件上传到S3,下载到同一地区的EC2上,在那里进行压缩,然后将其重新上传到S3并删除第一个副本。你可以直接上传到EC2,然后在那里进行压缩,然后再从那里上传到S3。但现在,您已经将20GB的问题从本地计算机转移到了EC2实例。
最好的方法是继续使用当前的方法进行本地压缩,然后上传。

1

对于上传吞吐量而言,S3的一个非常重要的功能是并行上传。有几个工具可以实现这一点,例如aws cli,s3cmd或crossftp。通过.NET API,可以使用TransferUtility类来实现相同的功能。

如果确实需要压缩,请查看S3DistCP,这是一个可以使用多台机器并行传输并实时压缩的工具。


0

如果您正在使用.NET,您可以使用字符流,但仍需要一些本地存储空间大于20 GB。

此外,不幸的是,亚马逊的S3只是存储。您可能需要启动另一个服务(AWS),该服务可以运行一个程序,以便在存储上进行压缩。因此,您的应用程序上传并使用S3存储进行压缩。

如果您的项目较小,您可能希望考虑IaaS提供商而不是PaaS。这样,存储和应用程序可以在同一组服务器上。


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