使用 Amazon S3 Transfer Manager 传输文件和目录 - AWS SDK for Java 2.x

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

使用 Amazon S3 Transfer Manager 传输文件和目录

Amazon S3 Transfer Manager 是针对AWS SDK for Java 2.x 的一款开源高级文件传输工具。可以使用它将文件和目录传入和传出 Amazon Simple Storage Service (Amazon S3)。

基于 AWS CRT 的 S3 客户端启用了分段的基于 Java 的标准 S3 异步客户端基础上构建时,S3 Transfer Manager 可以利用分段上传 API字节范围提取等性能改进。

使用 S3 Transfer Manager,您还可以实时监控传输进度,并暂停传输以便日后执行。

开始使用

将依赖项添加到构建文件中

要在使用 S3 Transfer Manager 时获得增强的分段性能,请使用必要的依赖项配置构建文件。

Use the AWS CRT-based S3 client
<dependencyManagement> <dependencies> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>bom</artifactId> <version>2.27.211</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>s3-transfer-manager</artifactId> </dependency> <dependency> <groupId>software.amazon.awssdk.crt</groupId> <artifactId>aws-crt</artifactId> <version>0.29.1432</version> </dependency> </dependencies>

1 最新版本2最新版本

Use the Java-based S3 async client
<dependencyManagement> <dependencies> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>bom</artifactId> <version>2.27.211</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>s3-transfer-manager</artifactId> </dependency> </dependencies>

1 最新版本

创建 S3 Transfer Manager 的实例

要启用并行传输,必须传入基于 AWS CRT 的 S3 客户端或启用了分段功能的基于 Java 的 S3 异步客户端。以下示例演示如何使用自定义设置来配置 S3 Transfer Manager。

Use the AWS CRT-based S3 client
S3AsyncClient s3AsyncClient = S3AsyncClient.crtBuilder() .credentialsProvider(DefaultCredentialsProvider.create()) .region(Region.US_EAST_1) .targetThroughputInGbps(20.0) .minimumPartSizeInBytes(8 * MB) .build(); S3TransferManager transferManager = S3TransferManager.builder() .s3Client(s3AsyncClient) .build();
Use the Java-based S3 async client

如果构建文件中未包含 aws-crt 依赖项,则 S3 Transfer Manager 将在适用于 Java 的 SDK 2.x 中使用的基于 Java 的标准 S3 异步客户端的基础上构建。

S3 客户端的自定义配置 - 需要启用分段功能

S3AsyncClient s3AsyncClient = S3AsyncClient.builder() .multipartEnabled(true) .credentialsProvider(DefaultCredentialsProvider.create()) .region(Region.US_EAST_1) .build(); S3TransferManager transferManager = S3TransferManager.builder() .s3Client(s3AsyncClient) .build();

没有 S3 客户端配置 - 自动启用分段支持

S3TransferManager transferManager = S3TransferManager.create();

将文件上传到 S3 桶

以下示例显示了一个文件上传示例,其中选择使用了记录上传进度的 LoggingTransferListener

要使用 S3 Transfer Manager 将文件上传到 Amazon S3,请将 UploadFileRequest 对象传递给 S3TransferManageruploadFile 方法。

uploadFile 方法返回的 FileUpload 对象表示上传进程。请求完成后,CompletedFileUpload 对象将包含有关上传的信息。

public void trackUploadFile(S3TransferManager transferManager, String bucketName, String key, URI filePathURI) { UploadFileRequest uploadFileRequest = UploadFileRequest.builder() .putObjectRequest(b -> b.bucket(bucketName).key(key)) .addTransferListener(LoggingTransferListener.create()) // Add listener. .source(Paths.get(filePathURI)) .build(); FileUpload fileUpload = transferManager.uploadFile(uploadFileRequest); fileUpload.completionFuture().join(); /* The SDK provides a LoggingTransferListener implementation of the TransferListener interface. You can also implement the interface to provide your own logic. Configure log4J2 with settings such as the following. <Configuration status="WARN"> <Appenders> <Console name="AlignedConsoleAppender" target="SYSTEM_OUT"> <PatternLayout pattern="%m%n"/> </Console> </Appenders> <Loggers> <logger name="software.amazon.awssdk.transfer.s3.progress.LoggingTransferListener" level="INFO" additivity="false"> <AppenderRef ref="AlignedConsoleAppender"/> </logger> </Loggers> </Configuration> Log4J2 logs the progress. The following is example output for a 21.3 MB file upload. Transfer initiated... | | 0.0% |==== | 21.1% |============ | 60.5% |====================| 100.0% Transfer complete! */ }
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import software.amazon.awssdk.transfer.s3.S3TransferManager; import software.amazon.awssdk.transfer.s3.model.CompletedFileUpload; import software.amazon.awssdk.transfer.s3.model.FileUpload; import software.amazon.awssdk.transfer.s3.model.UploadFileRequest; import software.amazon.awssdk.transfer.s3.progress.LoggingTransferListener; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.nio.file.Paths; import java.util.UUID;

从 S3 桶下载文件

以下示例显示了一个下载示例,其中选择使用了记录下载进度的 LoggingTransferListener

要使用 S3 Transfer Manager 从 S3 桶下载对象,请构建 DownloadFileRequest 对象并将其传递给 downloadFile 方法。

S3TransferManagerdownloadFile 方法返回的 FileDownload 对象表示文件传输。下载完成后,CompletedFileDownload 包含对下载相关信息的访问权限。

public void trackDownloadFile(S3TransferManager transferManager, String bucketName, String key, String downloadedFileWithPath) { DownloadFileRequest downloadFileRequest = DownloadFileRequest.builder() .getObjectRequest(b -> b.bucket(bucketName).key(key)) .addTransferListener(LoggingTransferListener.create()) // Add listener. .destination(Paths.get(downloadedFileWithPath)) .build(); FileDownload downloadFile = transferManager.downloadFile(downloadFileRequest); CompletedFileDownload downloadResult = downloadFile.completionFuture().join(); /* The SDK provides a LoggingTransferListener implementation of the TransferListener interface. You can also implement the interface to provide your own logic. Configure log4J2 with settings such as the following. <Configuration status="WARN"> <Appenders> <Console name="AlignedConsoleAppender" target="SYSTEM_OUT"> <PatternLayout pattern="%m%n"/> </Console> </Appenders> <Loggers> <logger name="software.amazon.awssdk.transfer.s3.progress.LoggingTransferListener" level="INFO" additivity="false"> <AppenderRef ref="AlignedConsoleAppender"/> </logger> </Loggers> </Configuration> Log4J2 logs the progress. The following is example output for a 21.3 MB file download. Transfer initiated... |======= | 39.4% |=============== | 78.8% |====================| 100.0% Transfer complete! */ }
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import software.amazon.awssdk.core.exception.SdkException; import software.amazon.awssdk.core.sync.RequestBody; import software.amazon.awssdk.transfer.s3.S3TransferManager; import software.amazon.awssdk.transfer.s3.model.CompletedFileDownload; import software.amazon.awssdk.transfer.s3.model.DownloadFileRequest; import software.amazon.awssdk.transfer.s3.model.FileDownload; import software.amazon.awssdk.transfer.s3.progress.LoggingTransferListener; import java.io.IOException; import java.net.URISyntaxException; import java.net.URL; import java.nio.file.Files; import java.nio.file.NoSuchFileException; import java.nio.file.Path; import java.nio.file.Paths; import java.util.UUID;

将 Amazon S3 对象复制到另一个桶。

以下示例演示如何使用 S3 Transfer Manager 复制对象。

要开始将对象从一个 S3 桶复制到另一个桶,请创建一个基本的 CopyObjectRequest 实例。

接下来,将基本 CopyObjectRequest 封装在可由 S3 Transfer Manager 使用的 CopyRequest 中。

S3TransferManagercopy 方法返回的 Copy 对象表示复制进程。复制进程完成后,CompletedCopy 对象将包含有关响应的详细信息。

public String copyObject(S3TransferManager transferManager, String bucketName, String key, String destinationBucket, String destinationKey) { CopyObjectRequest copyObjectRequest = CopyObjectRequest.builder() .sourceBucket(bucketName) .sourceKey(key) .destinationBucket(destinationBucket) .destinationKey(destinationKey) .build(); CopyRequest copyRequest = CopyRequest.builder() .copyObjectRequest(copyObjectRequest) .build(); Copy copy = transferManager.copy(copyRequest); CompletedCopy completedCopy = copy.completionFuture().join(); return completedCopy.response().copyObjectResult().eTag(); }
注意

要使用 S3 Transfer Manager 执行跨区域复制,请在基于 AWS CRT 的 S3 客户端生成器上启用 crossRegionAccessEnabled,如以下代码段所示。

S3AsyncClient s3AsyncClient = S3AsyncClient.crtBuilder() .crossRegionAccessEnabled(true) .build(); S3TransferManager transferManager = S3TransferManager.builder() .s3Client(s3AsyncClient) .build();
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import software.amazon.awssdk.core.sync.RequestBody; import software.amazon.awssdk.services.s3.model.CopyObjectRequest; import software.amazon.awssdk.transfer.s3.S3TransferManager; import software.amazon.awssdk.transfer.s3.model.CompletedCopy; import software.amazon.awssdk.transfer.s3.model.Copy; import software.amazon.awssdk.transfer.s3.model.CopyRequest; import java.util.UUID;

将本地目录上传到 S3 桶

以下示例演示如何将本地目录上传到 S3。

首先,调用 S3TransferManager 实例的 uploadDirectory 方法,传入 UploadDirectoryRequest

DirectoryUpload 对象表示上传进程,该进程会在请求完成时生成 CompletedDirectoryUploadCompleteDirectoryUpload 对象包含有关传输结果的信息,包括哪些文件传输失败。

public Integer uploadDirectory(S3TransferManager transferManager, URI sourceDirectory, String bucketName) { DirectoryUpload directoryUpload = transferManager.uploadDirectory(UploadDirectoryRequest.builder() .source(Paths.get(sourceDirectory)) .bucket(bucketName) .build()); CompletedDirectoryUpload completedDirectoryUpload = directoryUpload.completionFuture().join(); completedDirectoryUpload.failedTransfers() .forEach(fail -> logger.warn("Object [{}] failed to transfer", fail.toString())); return completedDirectoryUpload.failedTransfers().size(); }
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import software.amazon.awssdk.services.s3.model.ObjectIdentifier; import software.amazon.awssdk.transfer.s3.S3TransferManager; import software.amazon.awssdk.transfer.s3.model.CompletedDirectoryUpload; import software.amazon.awssdk.transfer.s3.model.DirectoryUpload; import software.amazon.awssdk.transfer.s3.model.UploadDirectoryRequest; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.nio.file.Paths; import java.util.UUID;

将 S3 桶对象下载到本地目录

您可以将 S3 桶中的对象下载到本地目录,如以下示例所示。

要将 S3 桶中的对象下载到本地目录,请首先调用 Transfer Manager 的 downloadDirectory 方法,传入 DownloadDirectoryRequest

DirectoryDownload 对象表示下载进程,该进程在请求完成时生成 CompletedDirectoryDownloadCompleteDirectoryDownload 对象包含有关传输结果的信息,包括哪些文件传输失败。

public Integer downloadObjectsToDirectory(S3TransferManager transferManager, URI destinationPathURI, String bucketName) { DirectoryDownload directoryDownload = transferManager.downloadDirectory(DownloadDirectoryRequest.builder() .destination(Paths.get(destinationPathURI)) .bucket(bucketName) .build()); CompletedDirectoryDownload completedDirectoryDownload = directoryDownload.completionFuture().join(); completedDirectoryDownload.failedTransfers() .forEach(fail -> logger.warn("Object [{}] failed to transfer", fail.toString())); return completedDirectoryDownload.failedTransfers().size(); }
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import software.amazon.awssdk.core.sync.RequestBody; import software.amazon.awssdk.services.s3.model.ObjectIdentifier; import software.amazon.awssdk.transfer.s3.S3TransferManager; import software.amazon.awssdk.transfer.s3.model.CompletedDirectoryDownload; import software.amazon.awssdk.transfer.s3.model.DirectoryDownload; import software.amazon.awssdk.transfer.s3.model.DownloadDirectoryRequest; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.HashSet; import java.util.Set; import java.util.UUID; import java.util.stream.Collectors;

查看完整示例

GitHub 中包含本页上所有示例的完整代码。