将传输管理器从版本 1 迁移到版本 2 适用于 Java 的 Amazon SDK - Amazon SDK for Java 2.x
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

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

将传输管理器从版本 1 迁移到版本 2 适用于 Java 的 Amazon SDK

本迁移指南涵盖了传输管理器 v1 和 S3 Transfer Manager v2 之间的主要区别,包括构造函数更改、方法映射和常见操作的代码示例。查看这些差异后,您可以成功迁移现有的 Transfer Manager 代码,以利用 v2 中改进的性能和异步操作。

关于 Amazon SDK 迁移工具

适用于 Java 的 Amazon SDK 提供了一种自动迁移工具,可以将 v1 传输管理器 API 的大部分迁移到 v2。但是,迁移工具不支持 v1 传输管理器的多项功能。对于这些情况,您需要按照本主题中的指南手动迁移传输管理器代码。

在本指南中,迁移状态显示了迁移工具是否可以自动迁移构造函数、方法或功能:

  • 支持:迁移工具可以自动转换此代码

  • 不支持:您需要手动迁移代码

即使对于标记为 “支持” 的项目,也要查看迁移结果并进行彻底测试。Transfer Manager 迁移涉及从同步操作到异步操作的重大架构更改。

概览

S3 传输管理器 v2 对传输管理器 API 进行了重大更改。S3 Transfer Manager v2 Amazon 基于异步操作构建,可提供更好的性能,尤其是在您使用基于 CRT 的 Amazon S3 客户端时。

主要区别

  • P@@ ac kage: com.amazonaws.services.s3.transfersoftware.amazon.awssdk.transfer.s3

  • 类名:TransferManagerS3TransferManager

  • 客户端依赖关系:同步 Amazon S3 客户端 → 异步亚马逊 S3 客户端 (S3AsyncClient)

  • 架构:同步操作 → 异步操作 CompletableFuture

  • 性能:通过 Amazon 基于 CRT 的客户端支持得到增强

高级别更改

方面 V1 第 2 版
Maven 依赖关系 aws-java-sdk-s3 s3-transfer-manager
com.amazonaws.services.s3.transfer software.amazon.awssdk.transfer.s3
主课 TransferManager S3TransferManager
亚马逊 S3 客户端 AmazonS3(同步) S3AsyncClient(异步)
返回类型 封锁操作 CompletableFuture<T>

Maven 依赖项

V1 第 2 版
<dependencyManagement> <dependencies> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-java-sdk-bom</artifactId> <version>>1.12.7871</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-java-sdk-s3</artifactId> </dependency> </dependencies>
<dependencyManagement> <dependencies> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>bom</artifactId> <version>2.31.682</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>s3-transfer-manager</artifactId> </dependency> <!-- Optional: For enhanced performance with Amazon CRT --> <dependency> <groupId>software.amazon.awssdk.crt</groupId> <artifactId>aws-crt</artifactId> <version>0.38.53</version> </dependency> </dependencies>

1 最新版本2 最新版本3 最新版本

客户端构造函数迁移

支持的构造函数(自动迁移)

V1 构造函数 等同于 V2 迁移状态
new TransferManager() S3TransferManager.create() 支持
TransferManagerBuilder. defaultTransferManager() S3TransferManager.create() 支持
TransferManagerBuilder. standard().build() S3TransferManager.builder().build() 支持
new TransferManager(AWSCredentials) S3TransferManager.builder() .s3Client(S3AsyncClient.builder() .credentialsProvider(...).build()) .build() 支持
new TransferManager( AWSCredentialsProvider) S3TransferManager.builder() .s3Client(S3AsyncClient.builder() .credentialsProvider(...).build()) .build() 支持

不支持的构造函数(需要手动迁移)

V1 构造函数 等同于 V2 迁移注意事项
new TransferManager(AmazonS3) 需要手动迁移 S3AsyncClient单独创建
new TransferManager(AmazonS3, ExecutorService) 需要手动迁移 创建S3AsyncClient并配置执行器
new TransferManager(AmazonS3, ExecutorService, boolean) 需要手动迁移 shutDownThreadPools不支持参数

手动迁移示例

V1 代码:

AmazonS3 s3Client = AmazonS3ClientBuilder.defaultClient(); TransferManager transferManager = new TransferManager(s3Client);

V2 代码:

// Create an `S3AsyncClient` with similar configuration S3AsyncClient s3AsyncClient = S3AsyncClient.builder() .credentialsProvider(DefaultCredentialsProvider.create()) .build(); // Provide the configured `S3AsyncClient` to the S3 transfer manager builder. S3TransferManager transferManager = S3TransferManager.builder() .s3Client(s3AsyncClient) .build();

客户端方法迁移

目前,迁移工具支持基本copydownloaduploaduploadDirectorydownloadDirectoryresumeDownload、和resumeUpload方法。

核心传输方法

V1 方法 V2 方法 返回类型更改 迁移状态
upload(String, String, File) uploadFile(UploadFileRequest) UploadFileUpload 支持
upload(PutObjectRequest) upload(UploadRequest) UploadUpload 支持
download(String, String, File) downloadFile(DownloadFileRequest) DownloadFileDownload 支持
download(GetObjectRequest, File) downloadFile(DownloadFileRequest) DownloadFileDownload 支持
copy(String, String, String, String) copy(CopyRequest) CopyCopy 支持
copy(CopyObjectRequest) copy(CopyRequest) CopyCopy 支持
uploadDirectory(String, String, File, boolean) uploadDirectory( UploadDirectoryRequest) MultipleFileUploadDirectoryUpload 支持
downloadDirectory(String, String, File) downloadDirectory( DownloadDirectoryRequest) MultipleFileDownloadDirectoryDownload 支持

可续传方法

V1 方法 V2 方法 迁移状态
resumeUpload(PersistableUpload) resumeUploadFile(ResumableFileUpload) 支持
resumeDownload(PersistableDownload) resumeDownloadFile(ResumableFileDownload) 支持

生命周期方法

V1 方法 V2 方法 迁移状态
shutdownNow() close() 支持
shutdownNow(boolean) 使用close()方法手动调整代码 不支持

不支持的 V1 客户端方法

V1 方法 V2 替代方案 备注
abortMultipartUploads(String, Date) 使用低级 Amazon S3 客户端 不支持
getAmazonS3Client() 单独保存参考文献 不支持;v2 中没有 getter
getConfiguration() 单独保存参考文献 不支持;v2 中没有 getter
uploadFileList(...) uploadFile()拨打多个电话 不支持
copyTransferStateChangeListener参数的方法 使用 TransferListener 参见手动迁移示例
downloadS3ProgressListener参数的方法 使用 TransferListener 参见手动迁移示例

downloadDirectory具有 4 个或更多参数的方法

参见手动迁移示例
uploadObjectMetadataProvider参数的方法 在请求中设置元数据 参见手动迁移示例
uploadDirectory*Provider参数的方法 在请求中设置标签 参见手动迁移示例

copyTransferStateChangeListener参数的方法

  • copy(CopyObjectRequest copyObjectRequest, AmazonS3 srcS3, TransferStateChangeListener stateChangeListener)

  • copy(CopyObjectRequest copyObjectRequest, TransferStateChangeListener stateChangeListener)

// V1 ---------------------------------------------------------------------------------------------- // Initialize source S3 client AmazonS3 s3client = AmazonS3ClientBuilder.standard() .withRegion("us-west-2") .build(); // Initialize Transfer Manager TransferManager tm = TransferManagerBuilder.standard() .withS3Client(srcS3) .build(); CopyObjectRequest copyObjectRequest = new CopyObjectRequest( "amzn-s3-demo-source-bucket", "source-key", "amzn-s3-demo-destination-bucket", "destination-key" ); TransferStateChangeListener stateChangeListener = new TransferStateChangeListener() { @Override public void transferStateChanged(Transfer transfer, TransferState state) { //Implementation of the TransferStateChangeListener } }; Copy copy = tm.copy(copyObjectRequest, srcS3, stateChangeListener); // V2 ---------------------------------------------------------------------------------------------- S3AsyncClient s3AsyncClient = S3AsyncClient.builder() .region(Region.US_WEST_2) .build(); S3TransferManager transferManager = S3TransferManager.builder() .s3Client(s3AsyncClient) .build(); // Create transfer listener (equivalent to TransferStateChangeListener in v1) TransferListener transferListener = new TransferListener() { @Override public void transferInitiated(Context.TransferInitiated context) { //Implementation System.out.println("Transfer initiated"); } @Override public void bytesTransferred(Context.BytesTransferred context) { //Implementation System.out.println("Bytes transferred"); } @Override public void transferComplete(Context.TransferComplete context) { //Implementation System.out.println("Transfer completed!"); } @Override public void transferFailed(Context.TransferFailed context) { //Implementation System.out.println("Transfer failed"); } }; CopyRequest copyRequest = CopyRequest.builder() .copyObjectRequest(req -> req .sourceBucket("amzn-s3-demo-source-bucket") .sourceKey("source-key") .destinationBucket("amzn-s3-demo-destination-bucket") .destinationKey("destination-key") ) .addTransferListener(transferListener) // Configure the transferListener into the request .build(); Copy copy = transferManager.copy(copyRequest);

downloadS3ProgressListener参数的方法

  • download(GetObjectRequest getObjectRequest, File file, S3ProgressListener progressListener)

  • download(GetObjectRequest getObjectRequest, File file, S3ProgressListener progressListener, long timeoutMillis)

  • download(GetObjectRequest getObjectRequest, File file, S3ProgressListener progressListener, long timeoutMillis, boolean resumeOnRetry)

// V1 ---------------------------------------------------------------------------------------------- S3ProgressListener progressListener = new S3ProgressListener() { @Override public void progressChanged(com.amazonaws.event.ProgressEvent progressEvent) { long bytes = progressEvent.getBytesTransferred(); ProgressEventType eventType = progressEvent.getEventType(); // Use bytes and eventType as needed } @Override public void onPersistableTransfer(PersistableTransfer persistableTransfer) { } }; Download download1 = tm.download(getObjectRequest, file, progressListener); Download download2 = tm.download(getObjectRequest, file, progressListener, timeoutMillis) Download download3 = tm.download(getObjectRequest, file, progressListener, timeoutMillis, true) // V2 ---------------------------------------------------------------------------------------------- TransferListener transferListener = new TransferListener() { @Override public void transferInitiated(Context.InitializedContext context) { // Equivalent to ProgressEventType.TRANSFER_STARTED_EVENT System.out.println("Transfer initiated"); } @Override public void bytesTransferred(Context.BytesTransferred context) { // Equivalent to ProgressEventType.REQUEST_BYTE_TRANSFER_EVENT long bytes = context.bytesTransferred(); System.out.println("Bytes transferred: " + bytes); } @Override public void transferComplete(Context.TransferComplete context) { // Equivalent to ProgressEventType.TRANSFER_COMPLETED_EVENT System.out.println("Transfer completed"); } @Override public void transferFailed(Context.TransferFailed context) { // Equivalent to ProgressEventType.TRANSFER_FAILED_EVENT System.out.println("Transfer failed: " + context.exception().getMessage()); } }; DownloadFileRequest downloadFileRequest = DownloadFileRequest.builder() .getObjectRequest(getObjectRequest) .destination(file.toPath()) .addTransferListener(transferListener) .build(); // For download1 FileDownload download = transferManager.downloadFile(downloadFileRequest); // For download2 CompletedFileDownload completedFileDownload = download.completionFuture() .get(timeoutMillis, TimeUnit.MILLISECONDS); // For download3, the v2 SDK does not have a direct equiavalent to the `resumeOnRetry` method of v1. // If a download is interrupted, you need to start a new download request.

downloadDirectory具有 4 个或更多参数的方法

  • downloadDirectory(String bucketName, String keyPrefix, File destinationDirectory, boolean resumeOnRetry)

  • downloadDirectory(String bucketName, String keyPrefix, File destinationDirectory, boolean resumeOnRetry, KeyFilter filter)

  • downloadDirectory(String bucketName, String keyPrefix, File destinationDirectory, KeyFilter filter)

// V1 ---------------------------------------------------------------------------------------------- KeyFilter filter = new KeyFilter() { @Override public boolean shouldInclude(S3ObjectSummary objectSummary) { //Filter implementation } }; MultipleFileDownload multipleFileDownload = tm.downloadDirectory(bucketName, keyPrefix, destinationDirectory, filter); // V2 ---------------------------------------------------------------------------------------------- // The v2 SDK does not have a direct equiavalent to the `resumeOnRetry` method of v1. // If a download is interrupted, you need to start a new download request. DownloadFilter filter = new DownloadFilter() { @Override public boolean test(S3Object s3Object) { // Filter implementation. } }; DownloadDirectoryRequest downloadDirectoryRequest = DownloadDirectoryRequest.builder() .bucket(bucketName) .filter(filter) .listObjectsV2RequestTransformer(builder -> builder.prefix(keyPrefix)) .destination(destinationDirectory.toPath()) .build(); DirectoryDownload directoryDownload = transferManager.downloadDirectory(downloadDirectoryRequest);

uploadObjectMetadata参数的方法

  • upload(String bucketName, String key, InputStream input, ObjectMetadata objectMetadata)

// V1 ----------------------------------------------------------------------------------------------ObjectMetadata metadata = new ObjectMetadata(); ObjectMetadata metadata = new ObjectMetadata(); metadata.setContentType("text/plain"); // System-defined metadata metadata.setContentLength(22L); // System-defined metadata metadata.addUserMetadata("myKey", "myValue"); // User-defined metadata PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, key, inputStream, metadata); Upload upload = transferManager.upload("amzn-s3-demo-bucket", "my-key", inputStream, metadata); // V2 ---------------------------------------------------------------------------------------------- /* When you use an InputStream to upload in V2, you should specify the content length and use `RequestBody.fromInputStream()`. If you don't provide the content length, the entire stream will be buffered in memory. If you can't determine the content length, we recommend using the CRT-based S3 client. */ Map<String, String> userMetadata = new HashMap<>(); userMetadata.put("x-amz-meta-myKey", "myValue"); PutObjectRequest putObjectRequest = PutObjectRequest.builder() .bucket("amzn-s3-demo-bucket1") .key("k") .contentType("text/plain") //System-defined metadata usually has separate methods in the builder. .contentLength(22L) .metadata(userMetadata) //metadata() is only for user-defined metadata. .build(); UploadRequest uploadRequest = UploadRequest.builder() .putObjectRequest(putObjectRequest) .requestBody(AsyncRequestBody.fromInputStream(stream, 22L, executor)) .build(); transferManager.upload(uploadRequest).completionFuture().join();

uploadDirectoryObjectMetadataProvider参数

  • uploadDirectory(String bucketName, String virtualDirectoryKeyPrefix, File directory, boolean includeSubdirectories, ObjectMetadataProvider metadataProvider)

  • uploadDirectory(String bucketName, String virtualDirectoryKeyPrefix, File directory, boolean includeSubdirectories, ObjectMetadataProvider metadataProvider, ObjectTaggingProvider taggingProvider)

  • uploadDirectory(String bucketName, String virtualDirectoryKeyPrefix, File directory, boolean includeSubdirectories, ObjectMetadataProvider metadataProvider, ObjectTaggingProvider taggingProvider, ObjectCannedAclProvider cannedAclProvider)

// V1 ---------------------------------------------------------------------------------------------- tm.uploadDirectory(bucketName, virtualDirectoryKeyPrefix, directory, includeSubdirectories, metadataProvider) tm.uploadDirectory(bucketName, virtualDirectoryKeyPrefix, directory, includeSubdirectories, metadataProvider, taggingProvider) tm.uploadDirectory(bucketName, virtualDirectoryKeyPrefix, directory, includeSubdirectories, metadataProvider, taggingProvider, cannedAclProvider) // V2 ---------------------------------------------------------------------------------------------- UploadDirectoryRequest request = UploadDirectoryRequest.builder() .bucket(bucketName) .s3Prefix(virtualDirectoryKeyPrefix) .source(directory.toPath()) .maxDepth(includeSubdirectories ? Integer.MAX_VALUE : 1) .uploadFileRequestTransformer(builder -> { // 1.Replace `ObjectMetadataProvider`, `ObjectTaggingProvider`, and `ObjectCannedAclProvider` with an // `UploadFileRequestTransformer` that can combine the functionality of all three *Provider implementations. // 2. Convert your v1 `ObjectMetadata` to v2 `PutObjectRequest` parameters. // 3. Convert your v1 `ObjectTagging` to v2 `Tagging`. // 4. Convert your v1 `CannedAccessControlList` to v2 `ObjectCannedACL`. }) .build(); DirectoryUpload directoryUpload = transferManager.uploadDirectory(request);

模型对象迁移

在中 Amazon SDK for Java 2.x,许多TransferManager模型对象已经过重新设计,不再支持 v1 模型对象中可用的几个 getter 和 setter 方法。

在 v2 中,您可以使用CompletableFuture<T>类在传输完成时执行操作,无论是成功还是出现异常。如果需要,您可以使用该join()方法等待完成。

核心传输对象

V1 级别 V2 级别 迁移状态
TransferManager S3TransferManager 支持
TransferManagerBuilder S3TransferManager.Builder 支持
Transfer Transfer 支持
AbortableTransfer Transfer 支持(没有单独的类)
Copy Copy 支持
Download FileDownload 支持
Upload Upload / FileUpload 支持
MultipleFileDownload DirectoryDownload 支持
MultipleFileUpload DirectoryUpload 支持

持久性对象

V1 级别 V2 级别 迁移状态
PersistableDownload ResumableFileDownload 支持
PersistableUpload ResumableFileUpload 支持
PersistableTransfer ResumableTransfer 支持
PauseResult<T> 直接可续传对象 不支持

结果对象

V1 级别 V2 级别 迁移状态
CopyResult CompletedCopy 支持
UploadResult CompletedUpload 支持

配置对象

V1 级别 V2 级别 迁移状态
TransferManagerConfiguration MultipartConfiguration(在亚马逊 S3 客户端上) 支持
TransferProgress TransferProgress + TransferProgressSnapshot 支持
KeyFilter DownloadFilter 支持

不支持的对象

V1 级别 V2 替代方案 迁移状态
PauseStatus 不支持 不支持
UploadContext 不支持 不支持
ObjectCannedAclProvider PutObjectRequest.builder().acl() 不支持
ObjectMetadataProvider PutObjectRequest.builder().metadata() 不支持
ObjectTaggingProvider PutObjectRequest.builder().tagging() 不支持
PresignedUrlDownload 不支持 不支持

TransferManagerBuilder 配置迁移

配置更改

您需要为 v2 传输管理器设置的配置更改取决于您使用的 S3 客户端。您可以选择 Amazon 基于 CRT 的 S3 客户端或基于 Java 的标准的 S3 异步客户端。有关差异的信息,请参阅中的 S3 客户端 Amazon SDK for Java 2.x主题。

Use the Amazon CRT-based S3 client
设置 v1 v2-使用 Amazon 基于 CRT 的 S3 客户端的传输管理器

(获取生成器)

TransferManagerBuilder tmBuilder = TransferManagerBuilder.standard();
S3TransferManager.Builder tmBuilder = S3TransferManager.builder();

S3 客户端

tmBuilder.withS3Client(...); tmBuilder.setS3Client(...);
tmBuilder.s3Client(...);

执行程序

tmBuilder.withExecutorFactory(...); tmBuilder.setExecutorFactory(...);
tmBuilder.executor(...);

关闭线程池

tmBuilder.withShutDownThreadPools(...); tmBuilder.setShutdownThreadPools(...);
不支持。关闭后,提供的执行者不会被关闭 S3TransferManager

最小上传段大小

tmBuilder.withMinimumUploadPartSize(...); tmBuilder.setMinimumUploadPartSize(...);
S3AsyncClient s3 = S3AsyncClient.crtBuilder(). minimumPartSizeInBytes(...).build(); tmBuilder.s3Client(s3);

分段上传阈值

tmBuilder.withMinimumUploadPartSize(...); tmBuilder.setMinimumUploadPartSize(...);
S3AsyncClient s3 = S3AsyncClient.crtBuilder(). thresholdInBytes(...).build(); tmBuilder.s3Client(s3);

最小复制段大小

tmBuilder.withMinimumUploadPartSize(...); tmBuilder.setMinimumUploadPartSize(...);
S3AsyncClient s3 = S3AsyncClient.crtBuilder(). minimumPartSizeInBytes(...).build(); tmBuilder.s3Client(s3);

分段复制阈值

tmBuilder.withMinimumUploadPartSize(...); tmBuilder.setMinimumUploadPartSize(...);
S3AsyncClient s3 = S3AsyncClient.crtBuilder(). thresholdInBytes(...).build(); tmBuilder.s3Client(s3);

禁用并行下载

tmBuilder.withDisableParallelDownloads(...); tmBuilder.setDisableParallelDownloads(...);
通过将禁用分段功能(默认)的基于 Java 的标准 S3 客户端传递给传输管理器,禁用并行下载。
S3AsyncClient s3 = S3AsyncClient.builder().build(); tmBuilder.s3Client(s3);

始终计算多分段 md5

tmBuilder.withAlwaysCalculateMultipartMd5(...); tmBuilder.setAlwaysCalculateMultipartMd5(...);
不支持。
Use Java-based S3 async client
设置 v1 v2-使用基于 Java 的 S3 异步客户端的传输管理器

(获取生成器)

TransferManagerBuilder tmBuilder = TransferManagerBuilder.standard();
S3TransferManager.Builder tmBuilder = S3TransferManager.builder();

S3 客户端

tmBuilder.withS3Client(...); tmBuilder.setS3Client(...);
tmBuilder.s3Client(...);

执行程序

tmBuilder.withExecutorFactory(...); tmBuilder.setExecutorFactory(...);
tmBuilder.executor(...);

关闭线程池

tmBuilder.withShutDownThreadPools(...); tmBuilder.setShutdownThreadPools(...);
不支持。关闭后,提供的执行者不会被关闭 S3TransferManager

最小上传段大小

tmBuilder.withMinimumUploadPartSize(...); tmBuilder.setMinimumUploadPartSize(...);
S3AsyncClient s3 = S3AsyncClient.builder() .multipartConfiguration(cfg -> cfg.minimumPartSizeInBytes(...)).build(); tmBuilder.s3Client(s3);

分段上传阈值

tmBuilder.withMinimumUploadPartSize(...); tmBuilder.setMinimumUploadPartSize(...);
S3AsyncClient s3 = S3AsyncClient.builder() .multipartConfiguration(cfg -> cfg.thresholdInBytes(...)).build(); tmBuilder.s3Client(s3);

最小复制段大小

tmBuilder.withMinimumUploadPartSize(...); tmBuilder.setMinimumUploadPartSize(...);
S3AsyncClient s3 = S3AsyncClient.builder() .multipartConfiguration(cfg -> cfg.minimumPartSizeInBytes(...)).build(); tmBuilder.s3Client(s3);

分段复制阈值

tmBuilder.withMinimumUploadPartSize(...); tmBuilder.setMinimumUploadPartSize(...);
S3AsyncClient s3 = S3AsyncClient.builder() .multipartConfiguration(cfg -> cfg.thresholdInBytes(...)).build(); tmBuilder.s3Client(s3);

禁用并行下载

tmBuilder.withDisableParallelDownloads(...); tmBuilder.setDisableParallelDownloads(...);
通过将禁用分段功能(默认)的基于 Java 的标准 S3 客户端传递给传输管理器,禁用并行下载。
S3AsyncClient s3 = S3AsyncClient.builder().build(); tmBuilder.s3Client(s3);

始终计算多分段 md5

tmBuilder.withAlwaysCalculateMultipartMd5(...); tmBuilder.setAlwaysCalculateMultipartMd5(...);
不支持。

行为更改

异步操作

V1(屏蔽):

Upload upload = transferManager.upload("amzn-s3-demo-bucket", "key", file); upload.waitForCompletion(); // Blocks until complete

V2(异步):

FileUpload upload = transferManager.uploadFile(UploadFileRequest.builder() .putObjectRequest(PutObjectRequest.builder() .bucket("amzn-s3-demo-bucket") .key("key") .build()) .source(file) .build()); CompletedFileUpload result = upload.completionFuture().join(); // Blocks until complete // Or handle asynchronously: upload.completionFuture().thenAccept(result -> { System.out.println("Upload completed: " + result.response().eTag()); });

错误处理

V1:如果任何子请求失败,则目录传输将完全失败。

V2:即使某些子请求失败,目录传输也能成功完成。明确检查错误:

DirectoryUpload directoryUpload = transferManager.uploadDirectory(request); CompletedDirectoryUpload result = directoryUpload.completionFuture().join(); // Check for failed transfers if (!result.failedTransfers().isEmpty()) { System.out.println("Some uploads failed:"); result.failedTransfers().forEach(failed -> System.out.println("Failed: " + failed.exception().getMessage())); }

通过字节范围提取进行并行下载

在 v2 SDK 中启用自动并行传输功能后,S3 传输管理器将使用字节范围提取来并行检索对象的特定部分(分段下载)。使用 v2 下载对象的方式不取决于对象最初的上传方式。所有下载都可以从高吞吐量和并发性中受益。

相比之下,对于 v1 的传输管理器,对象最初的上传方式确实很重要。v1 Transfer Manager 检索对象的各个部分的方式与上传分段的方式相同。如果对象最初是作为单个对象上传的,则 v1 传输管理器无法通过使用子请求来加速下载过程。