

 适用于 Java 的 Amazon SDK 1.x于2025年 end-of-support 12月31日达到。我们建议您迁移到 [Amazon SDK for Java 2.x](https://docs.amazonaws.cn/sdk-for-java/latest/developer-guide/home.html) 以继续获得新功能、可用性改进和安全更新。

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

# 使用 TransferManager 执行 Amazon S3 操作
<a name="examples-s3-transfermanager"></a>

您可以使用适用于 Java 的 Amazon SDK TransferManager 类可靠地将文件从本地环境传输到 Amazon S3 并将对象从一个 S3 位置复制到另一个 S3 位置。`TransferManager` 可获取传输进度，以及暂停或恢复上传和下载。

**注意**  
最佳实践  
建议您对 [ 存储桶启用 ](https://docs.amazonaws.cn/AmazonS3/latest/API/RESTBucketPUTlifecycle.html)AbortIncompleteMultipartUploadAmazon S3 生命周期规则。  
该规则指示 Amazon S3 中止在启动后没有在指定天数内完成的分段上传。当超过设置的时间限制时，Amazon S3 将中止上传，然后删除未完成的上传数据。  
有关更多信息，请参阅《Amazon S3 用户指南》中的[使用版本控制的桶生命周期配置](https://docs.amazonaws.cn/AmazonS3/latest/userguide/lifecycle-configuration-bucket-with-versioning.html)。

**注意**  
这些代码示例假定您了解[使用适用于 Java 的 Amazon SDK](basics.md) 中的内容，并且已使用[设置用于开发的 Amazon 凭证和区域](setup-credentials.md)中的信息配置默认 Amazon 凭证。

## 上传文件和目录
<a name="transfermanager-uploading"></a>

TransferManager 可将文件、文件列表和目录上传到您[之前创建](examples-s3-buckets.md#create-bucket)的任何 Amazon S3 桶。

**Topics**
+ [上传单个文件](#transfermanager-upload-file)
+ [上传文件列表](#transfermanager-upload-file-list)
+ [上传目录](#transfermanager-upload-directory)

### 上传单个文件
<a name="transfermanager-upload-file"></a>

调用 TransferManager 的 `upload` 方法，提供 Amazon S3 桶名称、键（对象）名称和代表要上传的文件的标准 Java [File](https://docs.oracle.com/javase/8/docs/api/index.html?java/io/File.html) 对象。

 **导入**。

```
import com.amazonaws.AmazonServiceException;
import com.amazonaws.services.s3.transfer.MultipleFileUpload;
import com.amazonaws.services.s3.transfer.TransferManager;
import com.amazonaws.services.s3.transfer.TransferManagerBuilder;
import com.amazonaws.services.s3.transfer.Upload;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
```

 **代码** 

```
File f = new File(file_path);
TransferManager xfer_mgr = TransferManagerBuilder.standard().build();
try {
    Upload xfer = xfer_mgr.upload(bucket_name, key_name, f);
    // loop with Transfer.isDone()
    XferMgrProgress.showTransferProgress(xfer);
    //  or block with Transfer.waitForCompletion()
    XferMgrProgress.waitForCompletion(xfer);
} catch (AmazonServiceException e) {
    System.err.println(e.getErrorMessage());
    System.exit(1);
}
xfer_mgr.shutdownNow();
```

`upload` 方法*立即*返回值，为您提供一个 `Upload` 对象，用于检查传输状态或等待传输完成。

请参阅[等待传输完成](#transfermanager-wait-for-completion)以了解有关在调用 TransferManager 的 `shutdownNow` 方法之前使用 `waitForCompletion` 成功完成传输的信息。在等待传输完成时，您可以轮询或侦听有关其状态和进度的更新。有关更多信息，请参阅[获取传输状态和进度](#transfermanager-get-status-and-progress)。

请参阅 GitHub 上的[完整示例](https://github.com/awsdocs/aws-doc-sdk-examples/blob/master/java/example_code/s3/src/main/java/aws/example/s3/XferMgrUpload.java)。

### 上传文件列表
<a name="transfermanager-upload-file-list"></a>

要通过一次操作上传多个文件，请调用 TransferManager `uploadFileList` 方法，并为其提供：
+ Amazon S3 存储桶名称
+ 一个*键前缀*，它将添加到创建的对象名称的前面 (将对象放置到的存储桶中的路径)
+ 一个 [File](https://docs.oracle.com/javase/8/docs/api/index.html?java/io/File.html) 对象，此对象表示将从中创建文件路径的相对目录
+ 一个 [List](https://docs.oracle.com/javase/8/docs/api/index.html?java/util/List.html) 对象，包含一组要上传的 [File](https://docs.oracle.com/javase/8/docs/api/index.html?java/io/File.html) 对象

 **导入**。

```
import com.amazonaws.AmazonServiceException;
import com.amazonaws.services.s3.transfer.MultipleFileUpload;
import com.amazonaws.services.s3.transfer.TransferManager;
import com.amazonaws.services.s3.transfer.TransferManagerBuilder;
import com.amazonaws.services.s3.transfer.Upload;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
```

 **代码** 

```
ArrayList<File> files = new ArrayList<File>();
for (String path : file_paths) {
    files.add(new File(path));
}

TransferManager xfer_mgr = TransferManagerBuilder.standard().build();
try {
    MultipleFileUpload xfer = xfer_mgr.uploadFileList(bucket_name,
            key_prefix, new File("."), files);
    // loop with Transfer.isDone()
    XferMgrProgress.showTransferProgress(xfer);
    // or block with Transfer.waitForCompletion()
    XferMgrProgress.waitForCompletion(xfer);
} catch (AmazonServiceException e) {
    System.err.println(e.getErrorMessage());
    System.exit(1);
}
xfer_mgr.shutdownNow();
```

请参阅[等待传输完成](#transfermanager-wait-for-completion)以了解有关在调用 TransferManager 的 `shutdownNow` 方法之前使用 `waitForCompletion` 成功完成传输的信息。在等待传输完成时，您可以轮询或侦听有关其状态和进度的更新。有关更多信息，请参阅[获取传输状态和进度](#transfermanager-get-status-and-progress)。

可使用由 `uploadFileList` 返回的 [MultipleFileUpload](https://docs.amazonaws.cn/sdk-for-java/v1/reference/com/amazonaws/services/s3/transfer/MultipleFileUpload.html) 对象来查询传输状态或进度。有关更多信息，请参阅[轮询传输的当前进度](#transfermanager-get-progress-polling)和[使用 ProgressListener 获取传输进度](#transfermanager-progress-listener)。

您也可以使用 `MultipleFileUpload` 的 `getSubTransfers` 方法为要传输的每个文件获取单个 `Upload` 对象。有关更多信息，请参阅[获取子传输的进度](#transfermanager-get-subtransfer-progress)。

请参阅 GitHub 上的[完整示例](https://github.com/awsdocs/aws-doc-sdk-examples/blob/master/java/example_code/s3/src/main/java/aws/example/s3/XferMgrUpload.java)。

### 上传目录
<a name="transfermanager-upload-directory"></a>

可使用 TransferManager 的 `uploadDirectory` 方法通过用于以递归方式复制子目录中的文件的选项来上传整个文件目录。您提供一个 Amazon S3 存储桶名称、一个 S3 键前缀、一个表示要复制的本地目录的 [File](https://docs.oracle.com/javase/8/docs/api/index.html?java/io/File.html) 对象和一个 `boolean` 值，该值指示您是否需要以递归方式复制子目录（*true* 或 *false*）。

 **导入**。

```
import com.amazonaws.AmazonServiceException;
import com.amazonaws.services.s3.transfer.MultipleFileUpload;
import com.amazonaws.services.s3.transfer.TransferManager;
import com.amazonaws.services.s3.transfer.TransferManagerBuilder;
import com.amazonaws.services.s3.transfer.Upload;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
```

 **代码** 

```
TransferManager xfer_mgr = TransferManagerBuilder.standard().build();
try {
    MultipleFileUpload xfer = xfer_mgr.uploadDirectory(bucket_name,
            key_prefix, new File(dir_path), recursive);
    // loop with Transfer.isDone()
    XferMgrProgress.showTransferProgress(xfer);
    // or block with Transfer.waitForCompletion()
    XferMgrProgress.waitForCompletion(xfer);
} catch (AmazonServiceException e) {
    System.err.println(e.getErrorMessage());
    System.exit(1);
}
xfer_mgr.shutdownNow();
```

请参阅[等待传输完成](#transfermanager-wait-for-completion)以了解有关在调用 TransferManager 的 `shutdownNow` 方法之前使用 `waitForCompletion` 成功完成传输的信息。在等待传输完成时，您可以轮询或侦听有关其状态和进度的更新。有关更多信息，请参阅[获取传输状态和进度](#transfermanager-get-status-and-progress)。

可使用由 `uploadFileList` 返回的 [MultipleFileUpload](https://docs.amazonaws.cn/sdk-for-java/v1/reference/com/amazonaws/services/s3/transfer/MultipleFileUpload.html) 对象来查询传输状态或进度。有关更多信息，请参阅[轮询传输的当前进度](#transfermanager-get-progress-polling)和[使用 ProgressListener 获取传输进度](#transfermanager-progress-listener)。

您也可以使用 `MultipleFileUpload` 的 `getSubTransfers` 方法为要传输的每个文件获取单个 `Upload` 对象。有关更多信息，请参阅[获取子传输的进度](#transfermanager-get-subtransfer-progress)。

请参阅 GitHub 上的[完整示例](https://github.com/awsdocs/aws-doc-sdk-examples/blob/master/java/example_code/s3/src/main/java/aws/example/s3/XferMgrUpload.java)。

## 下载文件或目录
<a name="transfermanager-downloading"></a>

使用 TransferManager 类从 Amazon S3 下载单个文件（Amazon S3 对象）或目录（一个 Amazon S3 桶名称，后跟对象前缀）。

**Topics**
+ [下载单个文件](#transfermanager-download-file)
+ [下载目录](#tranfermanager-download-directory)

### 下载单个文件
<a name="transfermanager-download-file"></a>

使用 TransferManager 的 `download` 方法，并为其提供包含要下载的对象的 Amazon S3 桶名称、键（对象）名称和一个 [File](https://docs.oracle.com/javase/8/docs/api/index.html?java/io/File.html) 对象（该对象表示要在本地系统上创建的文件）。

 **导入**。

```
import com.amazonaws.AmazonServiceException;
import com.amazonaws.services.s3.transfer.Download;
import com.amazonaws.services.s3.transfer.MultipleFileDownload;
import com.amazonaws.services.s3.transfer.TransferManager;
import com.amazonaws.services.s3.transfer.TransferManagerBuilder;

import java.io.File;
```

 **代码** 

```
File f = new File(file_path);
TransferManager xfer_mgr = TransferManagerBuilder.standard().build();
try {
    Download xfer = xfer_mgr.download(bucket_name, key_name, f);
    // loop with Transfer.isDone()
    XferMgrProgress.showTransferProgress(xfer);
    // or block with Transfer.waitForCompletion()
    XferMgrProgress.waitForCompletion(xfer);
} catch (AmazonServiceException e) {
    System.err.println(e.getErrorMessage());
    System.exit(1);
}
xfer_mgr.shutdownNow();
```

请参阅[等待传输完成](#transfermanager-wait-for-completion)以了解有关在调用 TransferManager 的 `shutdownNow` 方法之前使用 `waitForCompletion` 成功完成传输的信息。在等待传输完成时，您可以轮询或侦听有关其状态和进度的更新。有关更多信息，请参阅[获取传输状态和进度](#transfermanager-get-status-and-progress)。

请参阅 GitHub 上的[完整示例](https://github.com/awsdocs/aws-doc-sdk-examples/blob/master/java/example_code/s3/src/main/java/aws/example/s3/XferMgrDownload.java)。

### 下载目录
<a name="tranfermanager-download-directory"></a>

要从 Amazon S3 下载一组共享一个公共键前缀的文件（类似于文件系统上的目录），可使用 TransferManager `downloadDirectory` 方法。该方法需要包含要下载的对象的 Amazon S3 存储桶名称、所有对象共享的对象前缀和一个 [File](https://docs.oracle.com/javase/8/docs/api/index.html?java/io/File.html) 对象（此对象表示要将文件下载到的本地系统目录）。如果指定目录尚不存在，将创建此目录。

 **导入**。

```
import com.amazonaws.AmazonServiceException;
import com.amazonaws.services.s3.transfer.Download;
import com.amazonaws.services.s3.transfer.MultipleFileDownload;
import com.amazonaws.services.s3.transfer.TransferManager;
import com.amazonaws.services.s3.transfer.TransferManagerBuilder;

import java.io.File;
```

 **代码** 

```
TransferManager xfer_mgr = TransferManagerBuilder.standard().build();

try {
    MultipleFileDownload xfer = xfer_mgr.downloadDirectory(
            bucket_name, key_prefix, new File(dir_path));
    // loop with Transfer.isDone()
    XferMgrProgress.showTransferProgress(xfer);
    // or block with Transfer.waitForCompletion()
    XferMgrProgress.waitForCompletion(xfer);
} catch (AmazonServiceException e) {
    System.err.println(e.getErrorMessage());
    System.exit(1);
}
xfer_mgr.shutdownNow();
```

请参阅[等待传输完成](#transfermanager-wait-for-completion)以了解有关在调用 TransferManager 的 `shutdownNow` 方法之前使用 `waitForCompletion` 成功完成传输的信息。在等待传输完成时，您可以轮询或侦听有关其状态和进度的更新。有关更多信息，请参阅[获取传输状态和进度](#transfermanager-get-status-and-progress)。

请参阅 GitHub 上的[完整示例](https://github.com/awsdocs/aws-doc-sdk-examples/blob/master/java/example_code/s3/src/main/java/aws/example/s3/XferMgrDownload.java)。

## 复制对象
<a name="transfermanager-copy-object"></a>

要将对象从一个 S3 桶复制到另一个 S3 桶，可使用 TransferManager `copy` 方法。

 **导入**。

```
import com.amazonaws.AmazonServiceException;
import com.amazonaws.services.s3.transfer.Copy;
import com.amazonaws.services.s3.transfer.TransferManager;
import com.amazonaws.services.s3.transfer.TransferManagerBuilder;
```

 **代码** 

```
System.out.println("Copying s3 object: " + from_key);
System.out.println("      from bucket: " + from_bucket);
System.out.println("     to s3 object: " + to_key);
System.out.println("        in bucket: " + to_bucket);

TransferManager xfer_mgr = TransferManagerBuilder.standard().build();
try {
    Copy xfer = xfer_mgr.copy(from_bucket, from_key, to_bucket, to_key);
    // loop with Transfer.isDone()
    XferMgrProgress.showTransferProgress(xfer);
    // or block with Transfer.waitForCompletion()
    XferMgrProgress.waitForCompletion(xfer);
} catch (AmazonServiceException e) {
    System.err.println(e.getErrorMessage());
    System.exit(1);
}
xfer_mgr.shutdownNow();
```

请参阅 GitHub 上的[完整示例](https://github.com/awsdocs/aws-doc-sdk-examples/blob/master/java/example_code/s3/src/main/java/aws/example/s3/XferMgrCopy.java)。

## 请等待传输完成。
<a name="transfermanager-wait-for-completion"></a>

如果可以在传输完成前阻止您的应用程序（或线程），则可使用 [Transfer](https://docs.amazonaws.cn/sdk-for-java/v1/reference/com/amazonaws/services/s3/transfer/Transfer.html) 接口的 `waitForCompletion` 方法来阻止它，直至传输完成或出现异常。

```
try {
    xfer.waitForCompletion();
} catch (AmazonServiceException e) {
    System.err.println("Amazon service error: " + e.getMessage());
    System.exit(1);
} catch (AmazonClientException e) {
    System.err.println("Amazon client error: " + e.getMessage());
    System.exit(1);
} catch (InterruptedException e) {
    System.err.println("Transfer interrupted: " + e.getMessage());
    System.exit(1);
}
```

如果您在调用 * *之前`waitForCompletion` 轮询事件、在单独线程上实施轮询机制或使用 [ProgressListener](https://docs.amazonaws.cn/sdk-for-java/v1/reference/com/amazonaws/event/ProgressListener.html) 异步接收进度更新，则可获取传输进度。

请参阅 GitHub 上的[完整示例](https://github.com/awsdocs/aws-doc-sdk-examples/blob/master/java/example_code/s3/src/main/java/aws/example/s3/XferMgrProgress.java)。

## 获取传输状态和进度
<a name="transfermanager-get-status-and-progress"></a>

TransferManager `upload*`、`download*` 和 `copy` 方法所返回的每个类均返回以下某个类的实例，具体取决于它是单文件操作还是多文件操作。


**​**  

| 类 | 返回方 | 
| --- | --- | 
|  [Copy（复制](https://docs.amazonaws.cn/sdk-for-java/v1/reference/com/amazonaws/services/s3/transfer/Copy.html)  |  `copy`  | 
|  [下载](https://docs.amazonaws.cn/sdk-for-java/v1/reference/com/amazonaws/services/s3/transfer/Download.html) 。 |  `download`  | 
|  [MultipleFileDownload](https://docs.amazonaws.cn/sdk-for-java/v1/reference/com/amazonaws/services/s3/transfer/MultipleFileDownload.html)  |  `downloadDirectory`  | 
|  [上传](https://docs.amazonaws.cn/sdk-for-java/v1/reference/com/amazonaws/services/s3/transfer/Upload.html)  |  `upload`  | 
|  [MultipleFileUpload](https://docs.amazonaws.cn/sdk-for-java/v1/reference/com/amazonaws/services/s3/transfer/MultipleFileUpload.html)  |  `uploadFileList`, `uploadDirectory`  | 

所有这些类都实施 [Transfer](https://docs.amazonaws.cn/sdk-for-java/v1/reference/com/amazonaws/services/s3/transfer/Transfer.html) 接口。`Transfer` 提供了用于获取传输进度、暂停或恢复传输以及获取传输的当前状态或最终状态的有用方法。

**Topics**
+ [轮询传输的当前进度](#transfermanager-get-progress-polling)
+ [使用 ProgressListener 获取传输进度](#transfermanager-progress-listener)
+ [获取子传输的进度](#transfermanager-get-subtransfer-progress)

### 轮询传输的当前进度
<a name="transfermanager-get-progress-polling"></a>

此循环打印传输的进度，在其运行时检查其当前进度，然后在传输完成时打印最终状态。

 **导入**。

```
import com.amazonaws.AmazonClientException;
import com.amazonaws.AmazonServiceException;
import com.amazonaws.event.ProgressEvent;
import com.amazonaws.event.ProgressListener;
import com.amazonaws.services.s3.transfer.*;
import com.amazonaws.services.s3.transfer.Transfer.TransferState;

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
```

 **代码** 

```
// print the transfer's human-readable description
System.out.println(xfer.getDescription());
// print an empty progress bar...
printProgressBar(0.0);
// update the progress bar while the xfer is ongoing.
do {
    try {
        Thread.sleep(100);
    } catch (InterruptedException e) {
        return;
    }
    // Note: so_far and total aren't used, they're just for
    // documentation purposes.
    TransferProgress progress = xfer.getProgress();
    long so_far = progress.getBytesTransferred();
    long total = progress.getTotalBytesToTransfer();
    double pct = progress.getPercentTransferred();
    eraseProgressBar();
    printProgressBar(pct);
} while (xfer.isDone() == false);
// print the final state of the transfer.
TransferState xfer_state = xfer.getState();
System.out.println(": " + xfer_state);
```

请参阅 GitHub 上的[完整示例](https://github.com/awsdocs/aws-doc-sdk-examples/blob/master/java/example_code/s3/src/main/java/aws/example/s3/XferMgrProgress.java)。

### 使用 ProgressListener 获取传输进度
<a name="transfermanager-progress-listener"></a>

您可以使用 [Transfer](https://docs.amazonaws.cn/sdk-for-java/v1/reference/com/amazonaws/services/s3/transfer/Transfer.html) 接口的 `addProgressListener` 方法将 [ProgressListener](https://docs.amazonaws.cn/sdk-for-java/v1/reference/com/amazonaws/event/ProgressListener.html) 附加到任何传输中。

[ProgressListener](https://docs.amazonaws.cn/sdk-for-java/v1/reference/com/amazonaws/event/ProgressListener.html) 只需要一个方法，即 `progressChanged`，此方法将采用 [ProgressEvent](https://docs.amazonaws.cn/sdk-for-java/v1/reference/com/amazonaws/event/ProgressEvent.html) 对象。您可以使用此对象获取操作的总字节数 (通过调用其 `getBytes` 方法) 和目前已传输的字节数 (通过调用 `getBytesTransferred`)。

 **导入**。

```
import com.amazonaws.AmazonClientException;
import com.amazonaws.AmazonServiceException;
import com.amazonaws.event.ProgressEvent;
import com.amazonaws.event.ProgressListener;
import com.amazonaws.services.s3.transfer.*;
import com.amazonaws.services.s3.transfer.Transfer.TransferState;

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
```

 **代码** 

```
File f = new File(file_path);
TransferManager xfer_mgr = TransferManagerBuilder.standard().build();
try {
    Upload u = xfer_mgr.upload(bucket_name, key_name, f);
    // print an empty progress bar...
    printProgressBar(0.0);
    u.addProgressListener(new ProgressListener() {
        public void progressChanged(ProgressEvent e) {
            double pct = e.getBytesTransferred() * 100.0 / e.getBytes();
            eraseProgressBar();
            printProgressBar(pct);
        }
    });
    // block with Transfer.waitForCompletion()
    XferMgrProgress.waitForCompletion(u);
    // print the final state of the transfer.
    TransferState xfer_state = u.getState();
    System.out.println(": " + xfer_state);
} catch (AmazonServiceException e) {
    System.err.println(e.getErrorMessage());
    System.exit(1);
}
xfer_mgr.shutdownNow();
```

请参阅 GitHub 上的[完整示例](https://github.com/awsdocs/aws-doc-sdk-examples/blob/master/java/example_code/s3/src/main/java/aws/example/s3/XferMgrProgress.java)。

### 获取子传输的进度
<a name="transfermanager-get-subtransfer-progress"></a>

[MultipleFileUpload](https://docs.amazonaws.cn/sdk-for-java/v1/reference/com/amazonaws/services/s3/transfer/MultipleFileUpload.html) 类可通过调用其 `getSubTransfers` 方法来返回有关其子传输的信息。它将返回 [Upload](https://docs.oracle.com/javase/8/docs/api/index.html?java/util/Collection.html) 对象的不可修改的 [Collection](https://docs.amazonaws.cn/sdk-for-java/v1/reference/com/amazonaws/services/s3/transfer/Upload.html)，并单独提供每个子传输的传输状态和进度。

 **导入**。

```
import com.amazonaws.AmazonClientException;
import com.amazonaws.AmazonServiceException;
import com.amazonaws.event.ProgressEvent;
import com.amazonaws.event.ProgressListener;
import com.amazonaws.services.s3.transfer.*;
import com.amazonaws.services.s3.transfer.Transfer.TransferState;

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
```

 **代码** 

```
Collection<? extends Upload> sub_xfers = new ArrayList<Upload>();
sub_xfers = multi_upload.getSubTransfers();

do {
    System.out.println("\nSubtransfer progress:\n");
    for (Upload u : sub_xfers) {
        System.out.println("  " + u.getDescription());
        if (u.isDone()) {
            TransferState xfer_state = u.getState();
            System.out.println("  " + xfer_state);
        } else {
            TransferProgress progress = u.getProgress();
            double pct = progress.getPercentTransferred();
            printProgressBar(pct);
            System.out.println();
        }
    }

    // wait a bit before the next update.
    try {
        Thread.sleep(200);
    } catch (InterruptedException e) {
        return;
    }
} while (multi_upload.isDone() == false);
// print the final state of the transfer.
TransferState xfer_state = multi_upload.getState();
System.out.println("\nMultipleFileUpload " + xfer_state);
```

请参阅 GitHub 上的[完整示例](https://github.com/awsdocs/aws-doc-sdk-examples/blob/master/java/example_code/s3/src/main/java/aws/example/s3/XferMgrProgress.java)。

## 更多信息
<a name="transfermanager-see-also"></a>
+  《Amazon Simple Storage Service 用户指南》中的[对象键](https://docs.amazonaws.cn/AmazonS3/latest/dev/UsingMetadata.html)