

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 將 Transfer Manager 從 第 1 版遷移至 第 2 版 適用於 Java 的 AWS SDK
<a name="migration-s3-transfer-manager"></a>

此遷移指南涵蓋 Transfer Manager v1 和 S3 Transfer Manager v2 之間的主要差異，包括建構函數變更、方法映射和常見操作的程式碼範例。檢閱這些差異後，您可以成功遷移現有的 Transfer Manager 程式碼，以利用 v2 中改善的效能和非同步操作。

**關於 AWS SDK 遷移工具**  
 適用於 Java 的 AWS SDK 提供自動化[遷移工具](migration-tool.md)，可將大部分 v1 Transfer Manager API 遷移至 v2。不過，遷移工具不支援數個 v1 Transfer Manager 功能。在這些情況下，您需要使用本主題中的指引手動遷移 Transfer Manager 程式碼。  
在本指南中，**遷移狀態**會顯示遷移工具是否可以自動遷移建構函數、方法或功能：  
**支援**：遷移工具可以自動轉換此程式碼
**不支援**：您需要手動遷移程式碼
即使是標記為「支援」的項目，請檢閱遷移結果並徹底測試。Transfer Manager 遷移涉及從同步操作到非同步操作的重大架構變更。

## 概觀
<a name="s3-tm-migration-overview"></a>

S3 Transfer Manager v2 會將重大變更引入 Transfer Manager API。S3 Transfer Manager v2 建立在非同步操作上，並提供更好的效能，尤其是當您使用 AWS CRT 型 Amazon S3 用戶端時。

### 主要差異
<a name="s3-tm-migration-key-differences"></a>
+ **套件**：`com.amazonaws.services.s3.transfer`→ `software.amazon.awssdk.transfer.s3`
+ **類別名稱**：`TransferManager`→ `S3TransferManager`
+ **用戶端相依性**：同步 Amazon S3 用戶端 → 非同步 Amazon S3 用戶端 (`S3AsyncClient`)
+ **架構**：同步操作 → 使用 進行非同步操作 `CompletableFuture`
+ **效能**：透過 AWS CRT 型用戶端支援增強

## 高階變更
<a name="s3-tm-migration-high-level-changes"></a>


| 面向 | V1 | V2 | 
| --- | --- | --- | 
| Maven 相依性 | aws-java-sdk-s3 | s3-transfer-manager | 
| 套件 | com.amazonaws.services.s3.transfer | software.amazon.awssdk.transfer.s3 | 
| 主要類別 | TransferManager | S3TransferManager | 
| Amazon S3 用戶端 | AmazonS3 （同步） | S3AsyncClient （非同步） | 
| 傳回類型 | 封鎖操作 | CompletableFuture<T> | 

## Maven 相依性
<a name="s3-tm-migration-dependencies"></a>


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

1 [最新版本](https://central.sonatype.com/artifact/com.amazonaws/aws-java-sdk-bom)。 2 [最新版本](https://central.sonatype.com/artifact/software.amazon.awssdk/bom)。 3[最新版本](https://central.sonatype.com/artifact/software.amazon.awssdk.crt/aws-crt)。

## 用戶端建構函數遷移
<a name="s3-tm-migration-client-constructor"></a>

### 支援的建構函數 （自動遷移）
<a name="s3-tm-migration-supported-constructors"></a>


| 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() | 支援 | 

### 不支援的建構函數 （需要手動遷移）
<a name="s3-tm-migration-unsupported-constructors"></a>


| V1 建構函數 | V2 對等 | 遷移備註 | 
| --- | --- | --- | 
| new TransferManager(AmazonS3) | 需要手動遷移 | S3AsyncClient 分別建立 | 
| new TransferManager(AmazonS3, ExecutorService) | 需要手動遷移 | 建立 S3AsyncClient並設定執行器 | 
| new TransferManager(AmazonS3, ExecutorService, boolean) | 需要手動遷移 | shutDownThreadPools 不支援 參數 | 

### 手動遷移範例
<a name="s3-tm-migration-manual-examples"></a>

**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();
```

## 用戶端方法遷移
<a name="s3-tm-migration-client-methods"></a>

目前，遷移工具支援基本 `copy`、`download`、、`upload``uploadDirectory`、`downloadDirectory`、 `resumeDownload`和 `resumeUpload`方法。

### 核心傳輸方法
<a name="s3-tm-migration-core-transfer-methods"></a>


| V1 方法 | V2 方法 | 傳回類型變更 | 遷移狀態 | 
| --- | --- | --- | --- | 
| upload(String, String, File) | uploadFile(UploadFileRequest) | Upload → FileUpload | 支援 | 
| upload(PutObjectRequest) | upload(UploadRequest) | Upload → Upload | 支援 | 
| download(String, String, File) | downloadFile(DownloadFileRequest) | Download → FileDownload | 支援 | 
| download(GetObjectRequest, File) | downloadFile(DownloadFileRequest) | Download → FileDownload | 支援 | 
| copy(String, String, String, String) | copy(CopyRequest) | Copy → Copy | 支援 | 
| copy(CopyObjectRequest) | copy(CopyRequest) | Copy → Copy | 支援 | 
| uploadDirectory(String, String, File, boolean) | uploadDirectory( UploadDirectoryRequest) | MultipleFileUpload → DirectoryUpload | 支援 | 
| downloadDirectory(String, String, File) | downloadDirectory( DownloadDirectoryRequest) | MultipleFileDownload → DirectoryDownload | 支援 | 

### 可繼續傳輸方法
<a name="s3-tm-migration-resumable-methods"></a>


| V1 方法 | V2 方法 | 遷移狀態 | 
| --- | --- | --- | 
| resumeUpload(PersistableUpload) | resumeUploadFile(ResumableFileUpload) | 支援 | 
| resumeDownload(PersistableDownload) | resumeDownloadFile(ResumableFileDownload) | 支援 | 

### 生命週期方法
<a name="s3-tm-migration-lifecycle-methods"></a>


| V1 方法 | V2 方法 | 遷移狀態 | 
| --- | --- | --- | 
| shutdownNow() | close() | 支援 | 
| shutdownNow(boolean) | 使用 close()方法手動調整程式碼 | 不支援 | 

### 不支援的 V1 用戶端方法
<a name="s3-tm-migration-unsupported-methods"></a>


| V1 方法 | V2 替代方案 | 備註 | 
| --- | --- | --- | 
| abortMultipartUploads(String, Date) | 使用低階 Amazon S3 用戶端 | 不支援 | 
| getAmazonS3Client() | 分別儲存參考 | 不支援；v2 中沒有 getter | 
| getConfiguration() | 分別儲存參考 | 不支援；v2 中沒有 getter | 
| uploadFileList(...) | 進行多次uploadFile()呼叫 | 不支援 | 
| copy 具有 TransferStateChangeListener 參數的方法 | 使用 TransferListener | [請參閱手動遷移範例](#tm-unsupported-client-methods-copy) | 
| download 方法搭配 S3ProgressListener 參數 | 使用 [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/progress/TransferListener.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/progress/TransferListener.html) | [請參閱手動遷移範例](#tm-unsupported-client-methods-download) | 
|  `downloadDirectory` 具有 4 個或更多參數的方法  |  | [請參閱手動遷移範例](#tm-unsupported-client-methods-download-dir) | 
| upload 方法與 ObjectMetadataProvider 參數 | 在請求中設定中繼資料 | [請參閱手動遷移範例](#tm-unsupported-client-methods-upload) | 
| uploadDirectory 方法與 \$1Provider 參數 | 在請求中設定標籤 | [請參閱手動遷移範例](#tm-unsupported-client-methods-uploadDirectory) | 

#### `copy` 具有 `TransferStateChangeListener` 參數的方法
<a name="tm-unsupported-client-methods-copy"></a>
+ `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);
```

#### `download` 方法搭配 `S3ProgressListener` 參數
<a name="tm-unsupported-client-methods-download"></a>
+ `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 個或更多參數的方法
<a name="tm-unsupported-client-methods-download-dir"></a>
+ `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);
```

#### `upload` 方法與 `ObjectMetadata` 參數
<a name="tm-unsupported-client-methods-upload"></a>
+ `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();
```

#### `uploadDirectory` 使用 `ObjectMetadataProvider` 參數
<a name="tm-unsupported-client-methods-uploadDirectory"></a>
+ `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);
```

## 模型物件遷移
<a name="s3-tm-migration-model-objects"></a>

在 中 AWS SDK for Java 2.x，許多`TransferManager`模型物件已重新設計，不再支援 v1 模型物件中可用的多種 getter 和 setter 方法。

在 v2 中，您可以使用 `CompletableFuture<T>`類別在傳輸完成時執行動作，無論是成功還是例外。如有需要，您可以使用 `join()`方法等待完成。

### 核心傳輸物件
<a name="s3-tm-migration-core-transfer-objects"></a>


| V1 類別 | V2 類別 | 遷移狀態 | 
| --- | --- | --- | 
| TransferManager | S3TransferManager | 支援 | 
| TransferManagerBuilder | S3TransferManager.Builder | 支援 | 
| Transfer | Transfer | 支援 | 
| AbortableTransfer | Transfer | 支援 （無個別類別） | 
| Copy | Copy | 支援 | 
| Download | FileDownload | 支援 | 
| Upload | Upload / FileUpload | 支援 | 
| MultipleFileDownload | DirectoryDownload | 支援 | 
| MultipleFileUpload | DirectoryUpload | 支援 | 

### 持久性物件
<a name="s3-tm-migration-persistence-objects"></a>


| V1 類別 | V2 類別 | 遷移狀態 | 
| --- | --- | --- | 
| PersistableDownload | ResumableFileDownload | 支援 | 
| PersistableUpload | ResumableFileUpload | 支援 | 
| PersistableTransfer | ResumableTransfer | 支援 | 
| PauseResult<T> | 直接可繼續物件 | 不支援 | 

### 結果物件
<a name="s3-tm-migration-result-objects"></a>


| V1 類別 | V2 類別 | 遷移狀態 | 
| --- | --- | --- | 
| CopyResult | CompletedCopy | 支援 | 
| UploadResult | CompletedUpload | 支援 | 

### 組態物件
<a name="s3-tm-migration-configuration-objects"></a>


| V1 類別 | V2 類別 | 遷移狀態 | 
| --- | --- | --- | 
| TransferManagerConfiguration | MultipartConfiguration （在 Amazon S3 用戶端上） | 支援 | 
| TransferProgress | TransferProgress \$1 TransferProgressSnapshot | 支援 | 
| KeyFilter | DownloadFilter | 支援 | 

### 不支援的物件
<a name="s3-tm-migration-unsupported-objects"></a>


| V1 類別 | V2 替代方案 | 遷移狀態 | 
| --- | --- | --- | 
| PauseStatus | 不支援 | 不支援 | 
| UploadContext | 不支援 | 不支援 | 
| ObjectCannedAclProvider | PutObjectRequest.builder().acl() | 不支援 | 
| ObjectMetadataProvider | PutObjectRequest.builder().metadata() | 不支援 | 
| ObjectTaggingProvider | PutObjectRequest.builder().tagging() | 不支援 | 
| PresignedUrlDownload | 不支援 | 不支援 | 

## TransferManagerBuilder 組態遷移
<a name="s3-tm-migration-builder-configuration"></a>

### 組態變更
<a name="migration-transfer-manager-config-changes"></a>

您需要為 v2 Transfer Manager 設定的組態變更取決於您使用的 S3 用戶端。您可以選擇 AWS CRT 型 S3 用戶端或標準 Java 型 S3 非同步用戶端。如需差異的相關資訊，請參閱 [中的 S3 用戶端 AWS SDK for Java 2.x](examples-s3.md#s3-clients)主題。

------
#### [ Use the AWS CRT-based S3 client ]


****  

| 設定 | v1 | v2 - 使用 AWS CRT 型 S3 用戶端的 Transfer Manager | 
| --- | --- | --- | 
|    （取得建置器）  |  <pre>TransferManagerBuilder tmBuilder = <br />   TransferManagerBuilder.standard();</pre>  |  <pre>S3TransferManager.Builder tmBuilder  = <br />  S3TransferManager.builder();</pre>  | 
|    S3 用戶端  |  <pre>tmBuilder.withS3Client(...);<br />tmBuilder.setS3Client(...);</pre>  |  <pre>tmBuilder.s3Client(...);</pre>  | 
|    執行器  |  <pre>tmBuilder.withExecutorFactory(...);<br />tmBuilder.setExecutorFactory(...);</pre>  |  <pre>tmBuilder.executor(...);</pre>  | 
|    關閉執行緒集區  |  <pre>tmBuilder.withShutDownThreadPools(...);<br />tmBuilder.setShutdownThreadPools(...);</pre>  | 不支援。關閉 時，不會關閉提供的執行器 S3TransferManager  | 
|    最小上傳部分大小  |  <pre>tmBuilder.withMinimumUploadPartSize(...);<br />tmBuilder.setMinimumUploadPartSize(...);</pre>  |  <pre>S3AsyncClient s3 = S3AsyncClient.crtBuilder().<br />      minimumPartSizeInBytes(...).build();<br /><br />tmBuilder.s3Client(s3);</pre>  | 
|    分段上傳閾值  |  <pre>tmBuilder.withMultipartUploadThreshold(...);<br />tmBuilder.setMultipartUploadThreshold(...);</pre>  |  <pre>S3AsyncClient s3 = S3AsyncClient.crtBuilder().<br />      thresholdInBytes(...).build();<br /><br />tmBuilder.s3Client(s3);</pre>  | 
|    最小複製部分大小  |  <pre>tmBuilder.withMultipartCopyPartSize(...);<br />tmBuilder.setMultipartCopyPartSize(...);</pre>  |  <pre>S3AsyncClient s3 = S3AsyncClient.crtBuilder().<br />      minimumPartSizeInBytes(...).build();<br /><br />tmBuilder.s3Client(s3);</pre>  | 
|    分段複製閾值  |  <pre>tmBuilder.withMultipartCopyThreshold(...);<br />tmBuilder.setMultipartCopyThreshold(...);</pre>  |  <pre>S3AsyncClient s3 = S3AsyncClient.crtBuilder().<br />      thresholdInBytes(...).build();<br /><br />tmBuilder.s3Client(s3);</pre>  | 
|    停用平行下載  |  <pre>tmBuilder.withDisableParallelDownloads(...);<br />tmBuilder.setDisableParallelDownloads(...);</pre>  | 將停用分段 （預設） 的標準 Java 型 S3 用戶端傳遞給傳輸管理員，以停用平行下載。 <pre>S3AsyncClient s3 =<br />   S3AsyncClient.builder().build();<br /><br />tmBuilder.s3Client(s3);</pre> | 
|    一律計算分段 md5  |  <pre>tmBuilder.withAlwaysCalculateMultipartMd5(...);<br />tmBuilder.setAlwaysCalculateMultipartMd5(...);</pre>  | 不支援。 | 

------
#### [ Use Java-based S3 async client ]


****  

| 設定 | v1 | v2 - 使用 Java 型 S3 非同步用戶端的 Transfer Manager | 
| --- | --- | --- | 
|    （取得建置器）  |  <pre>TransferManagerBuilder tmBuilder = <br />   TransferManagerBuilder.standard();</pre>  |  <pre>S3TransferManager.Builder tmBuilder  = <br />  S3TransferManager.builder();</pre>  | 
|    S3 用戶端  |  <pre>tmBuilder.withS3Client(...);<br />tmBuilder.setS3Client(...);</pre>  |  <pre>tmBuilder.s3Client(...);</pre>  | 
|    執行器  |  <pre>tmBuilder.withExecutorFactory(...);<br />tmBuilder.setExecutorFactory(...);</pre>  |  <pre>tmBuilder.executor(...);</pre>  | 
|    關閉執行緒集區  |  <pre>tmBuilder.withShutDownThreadPools(...);<br />tmBuilder.setShutdownThreadPools(...);</pre>  | 不支援。關閉 時，不會關閉提供的執行器 S3TransferManager  | 
|    最小上傳部分大小  |  <pre>tmBuilder.withMinimumUploadPartSize(...);<br />tmBuilder.setMinimumUploadPartSize(...);</pre>  |  <pre>S3AsyncClient s3 = S3AsyncClient.builder()<br />    .multipartConfiguration(cfg -><br />        cfg.minimumPartSizeInBytes(...)).build();<br /><br />tmBuilder.s3Client(s3);</pre>  | 
|    分段上傳閾值  |  <pre>tmBuilder.withMultipartUploadThreshold(...);<br />tmBuilder.setMultipartUploadThreshold(...);</pre>  |  <pre>S3AsyncClient s3 = S3AsyncClient.builder()<br />    .multipartConfiguration(cfg -><br />        cfg.thresholdInBytes(...)).build();<br /><br />tmBuilder.s3Client(s3);</pre>  | 
|    最小複製部分大小  |  <pre>tmBuilder.withMultipartCopyPartSize(...);<br />tmBuilder.setMultipartCopyPartSize(...);</pre>  |  <pre>S3AsyncClient s3 = S3AsyncClient.builder()<br />    .multipartConfiguration(cfg -><br />        cfg.minimumPartSizeInBytes(...)).build();<br /><br />tmBuilder.s3Client(s3);</pre>  | 
|    分段複製閾值  |  <pre>tmBuilder.withMultipartCopyThreshold(...);<br />tmBuilder.setMultipartCopyThreshold(...);</pre>  |  <pre>S3AsyncClient s3 = S3AsyncClient.builder()<br />    .multipartConfiguration(cfg -><br />        cfg.thresholdInBytes(...)).build();<br /><br />tmBuilder.s3Client(s3);</pre>  | 
|    停用平行下載  |  <pre>tmBuilder.withDisableParallelDownloads(...);<br />tmBuilder.setDisableParallelDownloads(...);</pre>  | 將停用分段 （預設） 的標準 Java 型 S3 用戶端傳遞至傳輸管理員，以停用平行下載。 <pre>S3AsyncClient s3 =<br />   S3AsyncClient.builder().build();<br /><br />tmBuilder.s3Client(s3);</pre> | 
|    一律計算分段 md5  |  <pre>tmBuilder.withAlwaysCalculateMultipartMd5(...);<br />tmBuilder.setAlwaysCalculateMultipartMd5(...);</pre>  | 不支援。 | 

------

## 行為變更
<a name="s3-tm-migration-behavior-changes"></a>

### 非同步操作
<a name="s3-tm-migration-async-operations"></a>

**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());
});
```

### 錯誤處理
<a name="s3-tm-migration-error-handling"></a>

**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()));
}
```

### 透過位元組範圍擷取平行下載
<a name="migration-transfer-manager-behavior-fetches"></a>

在 v2 SDK 中啟用自動平行傳輸功能時，S3 Transfer Manager 會使用[位元組範圍擷取](https://docs.aws.amazon.com/AmazonS3/latest/userguide/optimizing-performance-guidelines.html#optimizing-performance-guidelines-get-range)來平行擷取物件的特定部分 （分段下載）。使用 v2 下載物件的方式，不取決於最初上傳物件的方式。所有下載都可以受益於高輸送量和並行。

相反地，與 v1 的 Transfer Manager 相比，最初上傳物件的方式並不重要。v1 Transfer Manager 擷取物件組件的方式與上傳組件的方式相同。如果物件最初是以單一物件上傳，v1 Transfer Manager 就無法使用子請求加速下載程序。