用Java流中S3中的unzip文件:s3-stream-unzip
#aws #java #s3 #unzip

我已经花了很多时间与AWS S3最近构建数据管道,并且遇到了S3存储桶中解压缩文件的令人惊讶的非平凡挑战。
与Google和Stackoverflow进行了几分钟,明确了许多其他人面临同一问题。

我将解释一些处理解压缩的选项以及导致我构建nejckorasa/s3-stream-unzip的最终解决方案。

总结:

  • 没有支持S3中的解压缩文件,
  • AWS SDK中也没有UNZIP内置API。

为了解压缩,您需要从S3下载文件,解压缩和上传解压缩文件。

使用Java AWS SDK,该解决方案易于实现,如果您要处理较小的文件,则可能足够好 - 如果文件足够小,您只需将解剖的文件保留在内存中并将其上传回去即可。

另外,如果有内存约束,则可以将文件持续到磁盘存储。太好了,有效。

较大的文件出现问题。 AWS Lambda,例如has a 1024MB memory and disk space limit。专用的EC2实例将解决磁盘空间问题,但需要更多的维护。我还认为将500MB+文件存储到磁盘上不是最佳方法。
当然,这将取决于需要解压缩多少个文件以及该操作的运行频率 - 这是一次性的,但如果需要每天运行,也许不是这样。无论如何,我们真的可以做得更好。

流解决方案

更好的方法是将文件从S3流式传输,将其下载,解压缩并将其上传回到使用Multipart上传的S3。这样,您就完全避免了需要磁盘存储的需求,并且可以通过调整下载和上传块尺寸来最大程度地减少内存足迹。

该解决方案的两个部分需要集成:

1)下载和uznip

流S3对象由AWS SDK本地支持,有一个getObjectContent()方法返回包含S3对象内容的输入流。

Java提供ZipInputStream作为输入流滤波器,用于读取zip文件格式的文件。它读取逐渐进入的邮政编码,因此允许每个条目进行自定义处理。

从s3中流对象内容并将其馈送到ZipInputStream中,我们可以在内存中缓冲我们可以缓冲的对象内容的块。

2)将未拉链的块上传到S3

将文件上传到S3是一项常见的任务,SDK支持几个选择,包括multipart upload

什么是多部分上传?

Multipart上传允许您将单个对象作为一组零件上传。
每个部分都是对象数据的连续部分。您可以独立和任何顺序上传这些对象零件。
如果任何零件的传输失败,您可以在不影响其他零件的情况下重新发送该零件。

上传对象的所有部分后,Amazon S3组装了这些零件并创建对象。

通常,当您的对象大小达到100 MB时,您应该考虑使用Multipart上传而不是将对象上传到单个操作中。

nejckorasa/s3-stream-unzip

现在剩下要做的就是集成流下载,解压缩和多部分上传。
我已经完成了所有的辛勤工作,并建立了nejckorasa/s3-stream-unzip

java库,用于管理AWS S3中大型文件和数据的解压缩,而无需事先知道大小,也不将其全部保留在记忆或写入磁盘中。

无需事先知道大小,而不将其全部保留在记忆或写入磁盘上。这使其适用于大型数据文件 - 它已用于解开100GB+。

的拉链文件。

它支持不同的解压缩策略,包括分配zipperiped文件的选项(适用于较大的文件,例如CSV文件)。它是轻巧的,仅需要Amazons3客户端。

它具有简单的API:

// initialize AmazonS3 client
AmazonS3 s3CLient = AmazonS3ClientBuilder.standard()
        // customize the client
        .build()

// create UnzipStrategy
var strategy = new NoSplitUnzipStrategy();
var strategy = new SplitTextUnzipStrategy()
        .withHeader(true)
        .withFileBytesLimit(100 * MB);

// or create UnzipStrategy with additional config
var config = new S3MultipartUpload.Config()
        .withThreadCount(5)
        .withQueueSize(5)
        .withAwaitTerminationTimeSeconds(2)
        .withCannedAcl(CannedAccessControlList.BucketOwnerFullControl)
        .withUploadPartBytesLimit(20 * MB)
        .withCustomizeInitiateUploadRequest(request -> {
            // customize request
            return request;
        });

var strategy = new NoSplitUnzipStrategy(config);

// create S3UnzipManager
var um = new S3UnzipManager(s3Client, strategy);
var um = new S3UnzipManager(s3Client, strategy.withContentTypes(List.of("application/zip"));

// unzip options
um.unzipObjects("bucket-name", "input-path", "output-path");
um.unzipObjectsKeyMatching("bucket-name", "input-path", "output-path", ".*\\.zip");
um.unzipObjectsKeyContaining("bucket-name", "input-path", "output-path", "-part-of-object-");
um.unzipObject(s3Object, "output-path");

库可在Maven CentralGithub上找到。

您可以在此处查看原始博客文章:https://nejckorasa.github.io/posts/s3-unzip/