将S3从一个存储桶复制到另一个存储桶的最快方法

时间:2019-05-23 06:53:56

标签: amazon-web-services amazon-s3 aws-lambda

我有一个文件,该文件在我的bucket1中用KMS key1加密。我需要将其传输到bucket2并使用KMS key2对其进行加密。我最初使用的是GetObject和PutObject API。但是,较大的文件(5GB及以上)需要花费很长时间。我也在lambda上执行此任务,因此超时为15分钟。

我尝试使用TransferManager下载API,但是它需要一个文件,并且遇到以下错误。我打算进行多部分下载,然后进行多部分上传。根据我的理解,由于需要使用key1解密文件然后使用key2加密文件,我无法使用多份副本,因为它使用了相同的Amazon S3客户端。

TransferManager sourceTransferManager = TransferManagerBuilder
                    .standard().withS3Client(sourceS3Client).build();
            GetObjectRequest getObjectRequest = new GetObjectRequest(srcBucket, srcKey);
            File modelFile = File.createTempFile("BigFile", "gz");
            logger.log("Starting download");
            Download download = sourceTransferManager.download(getObjectRequest, modelFile);
            download.waitForCompletion();
            sourceTransferManager.shutdownNow();
            logger.log("Finishing download");

            logger.log("Downloaded the object, let's upload it");
            //For a decrypted object, the content length in metadata still has the encrypted length
            //Set the content length to the unencrypted-data-length

            PutObjectRequest putObjectRequest = new PutObjectRequest(destS3Uri.getBucket(), destS3Uri.getKey(), modelFile);
            transferManager = TransferManagerBuilder
                    .standard()
                    .withS3Client(destS3Client)
                    .build();
            Upload upload = transferManager.upload(putObjectRequest);```

aused by: com.amazonaws.SdkClientException: Unable to store object contents to disk: No space left on device
at com.amazonaws.services.s3.internal.ServiceUtils.downloadToFile(ServiceUtils.java:314)
at com.amazonaws.services.s3.transfer.DownloadCallable.retryableDownloadS3ObjectToFile(DownloadCallable.java:275)
at com.amazonaws.services.s3.transfer.DownloadCallable.downloadAsSingleObject(DownloadCallable.java:92)
at com.amazonaws.services.s3.transfer.internal.AbstractDownloadCallable.call(AbstractDownloadCallable.java:102)
at com.amazonaws.services.s3.transfer.internal.AbstractDownloadCallable.call(AbstractDownloadCallable.java:40)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.io.IOException: No space left on device
at java.io.FileOutputStream.writeBytes(Native Method)
at java.io.FileOutputStream.write(FileOutputStream.java:326)
at java.io.BufferedOutputStream.write(BufferedOutputStream.java:122)
at com.amazonaws.services.s3.internal.ServiceUtils.downloadToFile(ServiceUtils.java:309)
... 8 more

1 个答案:

答案 0 :(得分:0)

即使存储桶位于不同帐户不同区域中,也可以使用CopyObject()方法在存储桶之间复制对象。 无需下载/上传对象!

假设您要从Bucket-A的{​​{1}}中的Region-A复制到Account-A的{​​{1}}中的Bucket-B。 / p>

有两种方法可以做到:

拉方法

  • 假设Region-B中有一个IAM用户(Account-B
  • User-B添加存储桶策略,该策略允许Account-B从存储桶列出/获取
  • 作为Bucket-A,将User-B中的User-B命令发送到Amazon S3(目标存储桶从源“拉”对象)

推送方法

  • 假设CopyObject()中有一个IAM用户(Region-B
  • User-A添加一个存储桶策略,该策略允许Account-A List / Put 到存储桶
  • 作为Bucket-B,将User-A中的User-A命令发送到Amazon S3(目标存储桶从源“拉”对象),并确保指定 ACL 作为CopyObject()。这样,目标存储桶(由其他帐户拥有)可以“拥有”复制的对象。这很重要!

我更喜欢'pull'方法,因为它不需要访问控制列表(ACL)的其他规范,因为Region-B拥有它复制的对象(与bucket-owner-full-control发送对象相反)到Account-B)。

如果这是一次性活动,我建议使用AWS Command-Line Interface (CLI),因为它非常易于使用。但是,如果您需要使其运行更多,则可能需要对其进行编码。