

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

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

# 使用适用于 Java 的 AWS SDK 的 Amazon S3 示例
<a name="examples-s3"></a>

此部分提供使用[适用于 Java 的 AWS SDK](https://aws.amazon.com/sdk-for-java/) 对 [Amazon S3](https://aws.amazon.com/s3/) 进行编程的示例。

**注意**  
这些示例仅包含演示每种方法所需的代码。[完整的示例代码在 GitHub 上提供](https://github.com/awsdocs/aws-doc-sdk-examples/tree/master/java)。您可以在那里下载单个源文件，也可以将存储库复制到本地以获得所有示例，然后构建并运行这些示例。

**Topics**
+ [创建、列出和删除 Amazon S3 桶](examples-s3-buckets.md)
+ [在 Amazon S3 对象上执行操作](examples-s3-objects.md)
+ [管理对桶和对象的 Amazon S3 访问权限](examples-s3-access-permissions.md)
+ [使用桶策略管理对 Amazon S3 桶的访问](examples-s3-bucket-policies.md)
+ [使用 TransferManager 执行 Amazon S3 操作](examples-s3-transfermanager.md)
+ [将 Amazon S3 桶配置为网站](examples-s3-website-configuration.md)
+ [使用 Amazon S3 客户端加密](examples-crypto.md)

# 创建、列出和删除 Amazon S3 桶
<a name="examples-s3-buckets"></a>

Amazon S3 中的每个对象（文件）必须放入*存储桶*，它代表对象的集合（容器）。每个存储桶使用必须唯一的*键* (名称) 命名。有关桶及其配置的详细信息，请参阅《Amazon Simple Storage Service 用户指南》中的[使用 Amazon S3 桶](https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingBucket.html)。

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

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

## 创建存储桶
<a name="create-bucket"></a>

使用 AmazonS3 客户端的 `createBucket` 方法。会返回新的[存储桶](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/services/s3/model/Bucket.html)。如果存储桶已存在，`createBucket` 方法将引发异常。

**注意**  
要尝试创建一个具有相同名称的存储桶来检查存储桶是否已存在，请调用 `doesBucketExist` 方法。如果存储桶存在，它将返回 `true`，否则将返回 `false`。

 **导入**。

```
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.AmazonS3Exception;
import com.amazonaws.services.s3.model.Bucket;

import java.util.List;
```

 **代码** 

```
if (s3.doesBucketExistV2(bucket_name)) {
    System.out.format("Bucket %s already exists.\n", bucket_name);
    b = getBucket(bucket_name);
} else {
    try {
        b = s3.createBucket(bucket_name);
    } catch (AmazonS3Exception e) {
        System.err.println(e.getErrorMessage());
    }
}
return b;
```

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

## 列出存储桶
<a name="list-buckets"></a>

使用 AmazonS3 客户端的 `listBucket` 方法。如果成功，会返回[存储桶](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/services/s3/model/Bucket.html)的列表。

 **导入**。

```
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.Bucket;

import java.util.List;
```

 **代码** 

```
List<Bucket> buckets = s3.listBuckets();
System.out.println("Your {S3} buckets are:");
for (Bucket b : buckets) {
    System.out.println("* " + b.getName());
}
```

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

## 删除存储桶
<a name="delete-bucket"></a>

在删除 Amazon S3 存储桶前，必须先确保存储桶为空，否则会导致错误。如果您的[存储桶受版本控制](https://docs.aws.amazon.com/AmazonS3/latest/dev/Versioning.html)，则必须同时删除与该存储桶关联的所有受版本控制对象。

**注意**  
[完整示例](https://github.com/awsdocs/aws-doc-sdk-examples/blob/master/java/example_code/s3/src/main/java/aws/example/s3/DeleteBucket.java)中依次包含上述每个步骤，提供用于删除 Amazon S3 存储桶及其内容的完整解决方案。

**Topics**
+ [删除不受版本控制的存储桶之前先删除其中的对象](#remove-objects-from-an-unversioned-bucket-before-deleting-it)
+ [删除受版本控制的存储桶之前先删除其中的对象](#remove-objects-from-a-versioned-bucket-before-deleting-it)
+ [删除空存储桶](#delete-an-empty-bucket)

### 删除不受版本控制的存储桶之前先删除其中的对象
<a name="remove-objects-from-an-unversioned-bucket-before-deleting-it"></a>

使用 AmazonS3 客户端的 `listObjects` 方法来检索对象列表，并使用 `deleteObject` 删除每个对象。

 **导入**。

```
import com.amazonaws.AmazonServiceException;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.*;

import java.util.Iterator;
```

 **代码** 

```
System.out.println(" - removing objects from bucket");
ObjectListing object_listing = s3.listObjects(bucket_name);
while (true) {
    for (Iterator<?> iterator =
         object_listing.getObjectSummaries().iterator();
         iterator.hasNext(); ) {
        S3ObjectSummary summary = (S3ObjectSummary) iterator.next();
        s3.deleteObject(bucket_name, summary.getKey());
    }

    // more object_listing to retrieve?
    if (object_listing.isTruncated()) {
        object_listing = s3.listNextBatchOfObjects(object_listing);
    } else {
        break;
    }
}
```

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

### 删除受版本控制的存储桶之前先删除其中的对象
<a name="remove-objects-from-a-versioned-bucket-before-deleting-it"></a>

如果您使用[受版本控制的存储桶](https://docs.aws.amazon.com/AmazonS3/latest/dev/Versioning.html)，还需要先删除存储桶中存储的所有受版本控制对象，然后才能删除存储桶。

使用在删除桶中的对象时所用的类似方法，通过使用 AmazonS3 客户端的 `listVersions` 方法列出所有受版本控制的对象，然后使用 `deleteVersion` 删除各个对象。

 **导入**。

```
import com.amazonaws.AmazonServiceException;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.*;

import java.util.Iterator;
```

 **代码** 

```
System.out.println(" - removing versions from bucket");
VersionListing version_listing = s3.listVersions(
        new ListVersionsRequest().withBucketName(bucket_name));
while (true) {
    for (Iterator<?> iterator =
         version_listing.getVersionSummaries().iterator();
         iterator.hasNext(); ) {
        S3VersionSummary vs = (S3VersionSummary) iterator.next();
        s3.deleteVersion(
                bucket_name, vs.getKey(), vs.getVersionId());
    }

    if (version_listing.isTruncated()) {
        version_listing = s3.listNextBatchOfVersions(
                version_listing);
    } else {
        break;
    }
}
```

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

### 删除空存储桶
<a name="delete-an-empty-bucket"></a>

在删除桶中的对象（包括所有受版本控制的对象）后，就可以使用 AmazonS3 客户端的 `deleteBucket` 方法删除桶本身。

 **导入**。

```
import com.amazonaws.AmazonServiceException;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.*;

import java.util.Iterator;
```

 **代码** 

```
System.out.println(" OK, bucket ready to delete!");
s3.deleteBucket(bucket_name);
```

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

# 在 Amazon S3 对象上执行操作
<a name="examples-s3-objects"></a>

Amazon S3 对象表示一个*文件* 或数据集合。每个对象必须驻留在一个[存储桶](examples-s3-buckets.md)中。

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

**Topics**
+ [上传对象](#upload-object)
+ [列出对象](#list-objects)
+ [下载对象](#download-object)
+ [复制、移动或重命名对象](#copy-object)
+ [删除对象](#delete-object)
+ [一次性删除多个对象](#delete-objects)

## 上传对象
<a name="upload-object"></a>

使用 AmazonS3 客户端的 `putObject` 方法，并为其提供桶名称、键名称和要上传的文件。*存储桶必须存在，否则将出现错误*。

 **导入**。

```
import com.amazonaws.AmazonServiceException;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
```

 **代码** 

```
System.out.format("Uploading %s to S3 bucket %s...\n", file_path, bucket_name);
final AmazonS3 s3 = AmazonS3ClientBuilder.standard().withRegion(Regions.DEFAULT_REGION).build();
try {
    s3.putObject(bucket_name, key_name, new File(file_path));
} catch (AmazonServiceException e) {
    System.err.println(e.getErrorMessage());
    System.exit(1);
}
```

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

## 列出对象
<a name="list-objects"></a>

要获取桶中的对象列表，请使用 AmazonS3 客户端的 `listObjects` 方法，并为其提供桶名称。

`listObjects` 方法返回一个 [ObjectListing](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/services/s3/model/ObjectListing.html) 对象，该对象提供有关存储桶中对象的信息。要列出对象名称（键），可使用 `getObjectSummaries` 方法获取 [S3ObjectSummary](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/services/s3/model/S3ObjectSummary.html) 对象的列表，其中每个对象均表示存储桶中的一个对象。然后调用其 `getKey` 方法以检索对象名称。

 **导入**。

```
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.ListObjectsV2Result;
import com.amazonaws.services.s3.model.S3ObjectSummary;
```

 **代码** 

```
System.out.format("Objects in S3 bucket %s:\n", bucket_name);
final AmazonS3 s3 = AmazonS3ClientBuilder.standard().withRegion(Regions.DEFAULT_REGION).build();
ListObjectsV2Result result = s3.listObjectsV2(bucket_name);
List<S3ObjectSummary> objects = result.getObjectSummaries();
for (S3ObjectSummary os : objects) {
    System.out.println("* " + os.getKey());
}
```

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

## 下载对象
<a name="download-object"></a>

使用 AmazonS3 客户端的 `getObject` 方法，并向其传递要下载的桶和对象的名称。如果成功，此方法将返回一个 [S3Object](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/services/s3/model/S3Object.html)。*指定的存储桶和对象键必须存在，否则将出现错误*。

您可以通过对 `getObjectContent` 调用 `S3Object` 来获取对象的内容。这将返回一个 [S3ObjectInputStream](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/services/s3/model/S3ObjectInputStream.html)，其行为与标准 Java `InputStream` 对象的相同。

以下示例从 S3 下载一个对象，然后将该对象的内容保存到一个文件（使用与对象键相同的名称）：

 **导入**。

```
import com.amazonaws.AmazonServiceException;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.S3Object;
import com.amazonaws.services.s3.model.S3ObjectInputStream;

import java.io.File;
```

 **代码** 

```
System.out.format("Downloading %s from S3 bucket %s...\n", key_name, bucket_name);
final AmazonS3 s3 = AmazonS3ClientBuilder.standard().withRegion(Regions.DEFAULT_REGION).build();
try {
    S3Object o = s3.getObject(bucket_name, key_name);
    S3ObjectInputStream s3is = o.getObjectContent();
    FileOutputStream fos = new FileOutputStream(new File(key_name));
    byte[] read_buf = new byte[1024];
    int read_len = 0;
    while ((read_len = s3is.read(read_buf)) > 0) {
        fos.write(read_buf, 0, read_len);
    }
    s3is.close();
    fos.close();
} catch (AmazonServiceException e) {
    System.err.println(e.getErrorMessage());
    System.exit(1);
} catch (FileNotFoundException e) {
    System.err.println(e.getMessage());
    System.exit(1);
} catch (IOException e) {
    System.err.println(e.getMessage());
    System.exit(1);
}
```

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

## 复制、移动或重命名对象
<a name="copy-object"></a>

您可以使用 AmazonS3 客户端的 `copyObject` 方法将对象从一个桶复制到另一个桶。它采用要从中复制的存储桶的名称、要复制的对象以及目标存储桶名称。

 **导入**。

```
import com.amazonaws.AmazonServiceException;
import com.amazonaws.regions.Regions;
```

 **代码** 

```
try {
    s3.copyObject(from_bucket, object_key, to_bucket, object_key);
} catch (AmazonServiceException e) {
    System.err.println(e.getErrorMessage());
    System.exit(1);
}
System.out.println("Done!");
```

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

**注意**  
您可以将 `copyObject` 与 [deleteObject](#delete-object) 配合使用来**移动**或**重命名**对象，方式是先将对象复制到新名称（您可以使用与源和目标相同的存储桶），然后从对象的旧位置删除对象。

## 删除对象
<a name="delete-object"></a>

使用 AmazonS3 客户端的 `deleteObject` 方法，并向其传递要删除的桶和对象的名称。*指定的存储桶和对象键必须存在，否则将出现错误*。

 **导入**。

```
import com.amazonaws.AmazonServiceException;
import com.amazonaws.regions.Regions;
```

 **代码** 

```
final AmazonS3 s3 = AmazonS3ClientBuilder.standard().withRegion(Regions.DEFAULT_REGION).build();
try {
    s3.deleteObject(bucket_name, object_key);
} catch (AmazonServiceException e) {
    System.err.println(e.getErrorMessage());
    System.exit(1);
}
```

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

## 一次性删除多个对象
<a name="delete-objects"></a>

使用 AmazonS3 客户端 `deleteObjects` 的方法，您可以将同一个桶中的多个对象的名称传递给 link:sdk-for-java/v1/reference/com/amazonaws/services/s3/model/DeleteObjectsRequest.html`` 方法，从而删除这些对象。

 **导入**。

```
import com.amazonaws.AmazonServiceException;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
```

 **代码** 

```
final AmazonS3 s3 = AmazonS3ClientBuilder.standard().withRegion(Regions.DEFAULT_REGION).build();
try {
    DeleteObjectsRequest dor = new DeleteObjectsRequest(bucket_name)
            .withKeys(object_keys);
    s3.deleteObjects(dor);
} catch (AmazonServiceException e) {
    System.err.println(e.getErrorMessage());
    System.exit(1);
}
```

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

# 管理对桶和对象的 Amazon S3 访问权限
<a name="examples-s3-access-permissions"></a>

您可以为 Amazon S3 存储桶和对象使用访问控制列表 (ACL)，以实现对 Amazon S3 资源的精细控制。

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

## 获取存储桶的访问控制列表
<a name="get-the-access-control-list-for-a-bucket"></a>

要获取桶的当前 ACL，请调用 AmazonS3 的 `getBucketAcl` 方法，将*桶名称* 传递给它以进行查询。此方法将返回 [AccessControlList](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/services/s3/model/AccessControlList.html) 对象。要获取列表中的每个访问授权，请调用其 `getGrantsAsList` 方法，这会返回一个包含 [Grant](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/services/s3/model/Grant.html) 对象的标准 Java 列表。

 **导入**。

```
import com.amazonaws.AmazonServiceException;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.AccessControlList;
import com.amazonaws.services.s3.model.Grant;
```

 **代码** 

```
final AmazonS3 s3 = AmazonS3ClientBuilder.standard().withRegion(Regions.DEFAULT_REGION).build();
try {
    AccessControlList acl = s3.getBucketAcl(bucket_name);
    List<Grant> grants = acl.getGrantsAsList();
    for (Grant grant : grants) {
        System.out.format("  %s: %s\n", grant.getGrantee().getIdentifier(),
                grant.getPermission().toString());
    }
} catch (AmazonServiceException e) {
    System.err.println(e.getErrorMessage());
    System.exit(1);
}
```

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

## 设置存储桶的访问控制列表
<a name="set-the-access-control-list-for-a-bucket"></a>

要添加或修改存储桶对 ACL 的权限，请调用 AmazonS3 的 `setBucketAcl` 方法。这需要一个 [AccessControlList](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/services/s3/model/AccessControlList.html) 对象，它包含被授权者和要设置的访问级别的列表。

 **导入**。

```
import com.amazonaws.AmazonServiceException;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.AccessControlList;
import com.amazonaws.services.s3.model.EmailAddressGrantee;
```

 **代码** 

```
final AmazonS3 s3 = AmazonS3ClientBuilder.standard().withRegion(Regions.DEFAULT_REGION).build();
try {
    // get the current ACL
    AccessControlList acl = s3.getBucketAcl(bucket_name);
    // set access for the grantee
    EmailAddressGrantee grantee = new EmailAddressGrantee(email);
    Permission permission = Permission.valueOf(access);
    acl.grantPermission(grantee, permission);
    s3.setBucketAcl(bucket_name, acl);
} catch (AmazonServiceException e) {
    System.err.println(e.getErrorMessage());
    System.exit(1);
}
```

**注意**  
您可以使用 [Grantee](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/services/s3/model/Grantee.html) 类直接提供被授权者的唯一标识符，也可以使用 [EmailAddressGrantee](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/services/s3/model/EmailAddressGrantee.html) 类通过电子邮件设置被授权者，这里采用后者。

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

## 获取对象的访问控制列表
<a name="get-the-access-control-list-for-an-object"></a>

要获取对象的当前 ACL，请调用 AmazonS3 的 `getObjectAcl` 方法，将*桶名称* 和*对象名称* 传递给它以进行查询。和 `getBucketAcl` 类似，此方法将返回一个 [AccessControlList](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/services/s3/model/AccessControlList.html) 对象，您可以用它来检查每个 [Grant](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/services/s3/model/Grant.html)。

 **导入**。

```
import com.amazonaws.AmazonServiceException;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.AccessControlList;
import com.amazonaws.services.s3.model.Grant;
```

 **代码** 

```
try {
    AccessControlList acl = s3.getObjectAcl(bucket_name, object_key);
    List<Grant> grants = acl.getGrantsAsList();
    for (Grant grant : grants) {
        System.out.format("  %s: %s\n", grant.getGrantee().getIdentifier(),
                grant.getPermission().toString());
    }
} catch (AmazonServiceException e) {
    System.err.println(e.getErrorMessage());
    System.exit(1);
}
```

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

## 设置对象的访问控制列表
<a name="set-the-access-control-list-for-an-object"></a>

要添加或修改对象对 ACL 的权限，请调用 AmazonS3 的 `setObjectAcl` 方法。这需要一个 [AccessControlList](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/services/s3/model/AccessControlList.html) 对象，它包含被授权者和要设置的访问级别的列表。

 **导入**。

```
import com.amazonaws.AmazonServiceException;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.AccessControlList;
import com.amazonaws.services.s3.model.EmailAddressGrantee;
```

 **代码** 

```
    try {
        // get the current ACL
        AccessControlList acl = s3.getObjectAcl(bucket_name, object_key);
        // set access for the grantee
        EmailAddressGrantee grantee = new EmailAddressGrantee(email);
        Permission permission = Permission.valueOf(access);
        acl.grantPermission(grantee, permission);
        s3.setObjectAcl(bucket_name, object_key, acl);
    } catch (AmazonServiceException e) {
        System.err.println(e.getErrorMessage());
        System.exit(1);
    }
}
```

**注意**  
您可以使用 [Grantee](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/services/s3/model/Grantee.html) 类直接提供被授权者的唯一标识符，也可以使用 [EmailAddressGrantee](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/services/s3/model/EmailAddressGrantee.html) 类通过电子邮件设置被授权者，这里采用后者。

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

## 更多信息
<a name="more-information"></a>
+  《Amazon S3 API Reference》中的 [GET Bucket acl](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketGETacl.html)
+  《Amazon S3 API Reference》中的 [PUT Bucket acl](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketPUTacl.html)
+  《Amazon S3 API Reference》中的 [GET Object acl](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectGETacl.html)
+  《Amazon S3 API Reference》中的 [PUT Object acl](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPUTacl.html)

# 使用桶策略管理对 Amazon S3 桶的访问
<a name="examples-s3-bucket-policies"></a>

您可以设置、获取或删除*存储桶策略* 来管理对 Amazon S3 存储桶的访问。

## 设置存储桶策略
<a name="set-s3-bucket-policy"></a>

您可以通过以下方式为特定的 S3 存储桶设置存储桶策略：
+ 调用 AmazonS3 客户端的 `setBucketPolicy` 并为其提供 [SetBucketPolicyRequest](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/services/s3/model/SetBucketPolicyRequest.html) 
+ 使用接收存储桶名称和策略文本 (JSON 格式) 的 `setBucketPolicy` 重载直接设置策略

 **导入**。

```
import com.amazonaws.AmazonServiceException;
import com.amazonaws.auth.policy.Policy;
import com.amazonaws.auth.policy.Principal;
```

 **代码** 

```
    s3.setBucketPolicy(bucket_name, policy_text);
} catch (AmazonServiceException e) {
    System.err.println(e.getErrorMessage());
    System.exit(1);
}
```

### 使用策略类生成或验证策略
<a name="use-s3-bucket-policy-class"></a>

为 `setBucketPolicy` 提供存储桶策略时，您可以执行以下操作：
+ 使用 JSON 格式的文本字符串直接指定策略
+ 使用 [Policy](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/auth/policy/Policy.html) 类构建策略

使用 `Policy` 类，您不必担心如何正确设置文本字符串的格式。要从 `Policy` 类获取 JSON 策略文本，请使用其 `toJson` 方法。

 **导入**。

```
import com.amazonaws.auth.policy.Resource;
import com.amazonaws.auth.policy.Statement;
import com.amazonaws.auth.policy.actions.S3Actions;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
```

 **代码** 

```
        new Statement(Statement.Effect.Allow)
                .withPrincipals(Principal.AllUsers)
                .withActions(S3Actions.GetObject)
                .withResources(new Resource(
                        "{region-arn}s3:::" + bucket_name + "/*")));
return bucket_policy.toJson();
```

`Policy` 类还提供 `fromJson` 方法，它会尝试使用传入的 JSON 字符串构建策略。该方法会验证文本以确保可以转换为有效策略结构，如果策略文本无效，就会失败并引发 `IllegalArgumentException`。

```
Policy bucket_policy = null;
try {
    bucket_policy = Policy.fromJson(file_text.toString());
} catch (IllegalArgumentException e) {
    System.out.format("Invalid policy text in file: \"%s\"",
            policy_file);
    System.out.println(e.getMessage());
}
```

您可以使用此方法，提前验证您从文件读入或通过其他方法得到的策略。

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

## 获取存储桶策略
<a name="get-s3-bucket-policy"></a>

要检索 Amazon S3 桶的策略，请调用 AmazonS3 客户端的 `getBucketPolicy` 方法，将桶名称传递给它以获取策略。

 **导入**。

```
import com.amazonaws.AmazonServiceException;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
```

 **代码** 

```
  try {
      BucketPolicy bucket_policy = s3.getBucketPolicy(bucket_name);
      policy_text = bucket_policy.getPolicyText();
  } catch (AmazonServiceException e) {
      System.err.println(e.getErrorMessage());
      System.exit(1);
  }
```

如果指定的存储桶不存在、您没有访问该存储桶的权限或者其中不包含存储桶策略，会引发 `AmazonServiceException`。

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

## 删除存储桶策略
<a name="delete-s3-bucket-policy"></a>

要删除桶策略，请调用 AmazonS3 客户端的 `deleteBucketPolicy`，并为其提供桶名称。

 **导入**。

```
import com.amazonaws.AmazonServiceException;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
```

 **代码** 

```
  try {
      s3.deleteBucketPolicy(bucket_name);
  } catch (AmazonServiceException e) {
      System.err.println(e.getErrorMessage());
      System.exit(1);
  }
```

即使存储桶中还没有策略，该方法也会成功。如果您指定的存储桶名称不存在，或者您没有访问该存储桶的权限，会引发 `AmazonServiceException`。

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

## 更多信息
<a name="more-info"></a>
+  《Amazon Simple Storage Service 用户指南》中的[访问策略语言概述](https://docs.aws.amazon.com/AmazonS3/latest/dev/access-policy-language-overview.html)
+  《Amazon Simple Storage Service 用户指南》中的[桶策略示例](https://docs.aws.amazon.com/AmazonS3/latest/dev/example-bucket-policies.html)

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

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

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

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

## 上传文件和目录
<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.aws.amazon.com/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.aws.amazon.com/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.aws.amazon.com/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.aws.amazon.com/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.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/services/s3/transfer/Copy.html)   |   `copy`   | 
|   [下载](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/services/s3/transfer/Download.html) 。  |   `download`   | 
|   [MultipleFileDownload](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/services/s3/transfer/MultipleFileDownload.html)   |   `downloadDirectory`   | 
|   [上传](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/services/s3/transfer/Upload.html)   |   `upload`   | 
|   [MultipleFileUpload](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/services/s3/transfer/MultipleFileUpload.html)   |   `uploadFileList`, `uploadDirectory`   | 

所有这些类都实施 [Transfer](https://docs.aws.amazon.com/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.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/services/s3/transfer/Transfer.html) 接口的 `addProgressListener` 方法将 [ProgressListener](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/event/ProgressListener.html) 附加到任何传输中。

[ProgressListener](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/event/ProgressListener.html) 只需要一个方法，即 `progressChanged`，此方法将采用 [ProgressEvent](https://docs.aws.amazon.com/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.aws.amazon.com/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.aws.amazon.com/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.aws.amazon.com/AmazonS3/latest/dev/UsingMetadata.html)

# 将 Amazon S3 桶配置为网站
<a name="examples-s3-website-configuration"></a>

您可以配置 Amazon S3 存储桶，使其具有与网站类似的行为。要执行此操作，您需要设置其网站配置。

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

## 设置存储桶的网站配置
<a name="set-a-bucket-s-website-configuration"></a>

要设置 Amazon S3 桶网站配置，请使用要设置配置的桶名称，以及包含桶网站配置的 [BucketWebsiteConfiguration](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/services/s3/model/BucketWebsiteConfiguration.html) 对象，来调用 AmazonS3 的 `setWebsiteConfiguration` 方法。

设置索引文档是*必需的*；所有其他参数都是可选的。

 **导入**。

```
import com.amazonaws.AmazonServiceException;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.BucketWebsiteConfiguration;
```

 **代码** 

```
    String bucket_name, String index_doc, String error_doc) {
BucketWebsiteConfiguration website_config = null;

if (index_doc == null) {
    website_config = new BucketWebsiteConfiguration();
} else if (error_doc == null) {
    website_config = new BucketWebsiteConfiguration(index_doc);
} else {
    website_config = new BucketWebsiteConfiguration(index_doc, error_doc);
}

final AmazonS3 s3 = AmazonS3ClientBuilder.standard().withRegion(Regions.DEFAULT_REGION).build();
try {
    s3.setBucketWebsiteConfiguration(bucket_name, website_config);
} catch (AmazonServiceException e) {
    System.out.format(
            "Failed to set website configuration for bucket '%s'!\n",
            bucket_name);
    System.err.println(e.getErrorMessage());
    System.exit(1);
}
```

**注意**  
设置网站配置不会修改您的存储桶的访问权限。要使您的文件在 Web 上可见，您还需要设置一个*存储桶策略*，允许对存储桶中文件的公共读取访问权限。有关更多信息，请参阅[使用桶策略管理对 Amazon S3 桶的访问](examples-s3-bucket-policies.md)。

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

## 获取存储桶的网站配置
<a name="get-a-bucket-s-website-configuration"></a>

要获取 Amazon S3 桶的网站配置，请使用要检索其配置的桶的名称来调用 AmazonS3 的 `getWebsiteConfiguration` 方法。

将以 [BucketWebsiteConfiguration](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/services/s3/model/BucketWebsiteConfiguration.html) 对象的形式返回配置。如果该存储桶没有网站配置，则会返回 `null`。

 **导入**。

```
import com.amazonaws.AmazonServiceException;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.BucketWebsiteConfiguration;
```

 **代码** 

```
final AmazonS3 s3 = AmazonS3ClientBuilder.standard().withRegion(Regions.DEFAULT_REGION).build();
try {
    BucketWebsiteConfiguration config =
            s3.getBucketWebsiteConfiguration(bucket_name);
    if (config == null) {
        System.out.println("No website configuration found!");
    } else {
        System.out.format("Index document: %s\n",
                config.getIndexDocumentSuffix());
        System.out.format("Error document: %s\n",
                config.getErrorDocument());
    }
} catch (AmazonServiceException e) {
    System.err.println(e.getErrorMessage());
    System.out.println("Failed to get website configuration!");
    System.exit(1);
}
```

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

## 删除存储桶的网站配置
<a name="delete-a-bucket-s-website-configuration"></a>

要删除 Amazon S3 桶的网站配置，请使用要从中删除配置的桶的名称来调用 AmazonS3 的 `deleteWebsiteConfiguration` 方法。

 **导入**。

```
import com.amazonaws.AmazonServiceException;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
```

 **代码** 

```
final AmazonS3 s3 = AmazonS3ClientBuilder.standard().withRegion(Regions.DEFAULT_REGION).build();
try {
    s3.deleteBucketWebsiteConfiguration(bucket_name);
} catch (AmazonServiceException e) {
    System.err.println(e.getErrorMessage());
    System.out.println("Failed to delete website configuration!");
    System.exit(1);
}
```

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

## 更多信息
<a name="more-information"></a>
+  《Amazon S3 API Reference》中的 [PUT Bucket website](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketPUTwebsite.html)
+  《Amazon S3 API Reference》中的 [GET Bucket website](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketGETwebsite.html)
+  《Amazon S3 API Reference》中的 [DELETE Bucket website](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketDELETEwebsite.html)

# 使用 Amazon S3 客户端加密
<a name="examples-crypto"></a>

使用 Amazon S3 加密客户端加密数据是您可以用于为存储在 Amazon S3 中的敏感信息提供一层额外保护的一种方法。此部分中的示例演示如何为您的应用程序创建和配置 Amazon S3 加密客户端。

如果您不熟悉加密，请参阅《AWS KMS 开发人员指南》中的[加密基础知识](https://docs.aws.amazon.com/kms/latest/developerguide/crypto-intro.html)，大致了解加密术语和加密算法。要了解有关所有 AWS SDK 的加密支持信息，请参阅 Amazon Web Services 一般参考中的 [Amazon S3 客户端加密的 AWS SDK 支持](https://docs.aws.amazon.com/general/latest/gr/aws_sdk_cryptography.html)。

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

如果您使用的是 1.11.836 或更低版本的适用于 Java 的 AWS SDK，请参阅 [Amazon S3 加密客户端迁移](s3-encryption-migration.md)，了解有关将应用程序迁移到更高版本的信息。如果您无法迁移，请参阅 GitHub 上的[此完整示例](https://github.com/awsdocs/aws-doc-sdk-examples/blob/master/java/example_code/s3/src/main/java/aws/example/s3/S3Encrypt.java)。

如果您使用的是 1.11.837 或更高版本的适用于 Java 的 AWS SDK，请浏览下面列出的示例主题以使用 Amazon S3 客户端加密。

**Topics**
+ [Amazon S3 客户端加密配合客户端主密钥](examples-crypto-masterkey.md)
+ [Amazon S3 客户端加密配合 AWS KMS 托管密钥](examples-crypto-kms.md)

# Amazon S3 客户端加密配合客户端主密钥
<a name="examples-crypto-masterkey"></a>

以下示例使用 [AmazonS3EncryptionClientV2Builder](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/services/s3/AmazonS3EncryptionClientV2Builder.html) 类创建启用客户端加密的 Amazon S3 客户端。启用后，您使用此客户端上传到 Amazon S3 的任何对象都将加密。您使用此客户端从 Amazon S3 获取的任何对象都将自动解密。

**注意**  
以下示例演示如何配合使用 Amazon S3 客户端加密和客户托管的客户端主密钥。要了解如何配合使用加密和 AWS KMS 托管密钥，请参阅 [Amazon S3 客户端加密配合 AWS 托管密钥](examples-crypto-kms.md)。

启用客户端 Amazon S3 加密时，您可以从两种加密模式中进行选择：经严格身份验证或经身份验证。以下部分说明了如何启用每种类型。要了解每种模式使用哪种算法，请参阅 [CryptoMode](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/services/s3/model/CryptoMode.html) 定义。

## 必需的导入
<a name="required-imports"></a>

为这些示例导入以下类。

 **导入**。

```
import com.amazonaws.ClientConfiguration;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3EncryptionClientV2Builder;
import com.amazonaws.services.s3.AmazonS3EncryptionV2;
import com.amazonaws.services.s3.model.CryptoConfigurationV2;
import com.amazonaws.services.s3.model.CryptoMode;
import com.amazonaws.services.s3.model.EncryptionMaterials;
import com.amazonaws.services.s3.model.StaticEncryptionMaterialsProvider;
```

## 经严格身份验证加密
<a name="strict-authenticated-encryption"></a>

如果未指定 `CryptoMode`，则默认模式为经严格身份验证加密。

要显式启用此模式，请在 `withCryptoConfiguration` 方法中指定 `StrictAuthenticatedEncryption` 值。

**注意**  
要使用客户端经身份验证加密，您必须将最新的 [Bouncy Castle jar](https://www.bouncycastle.org/download/bouncy-castle-java/) 文件加入应用程序的类路径中。

 **代码** 

```
AmazonS3EncryptionV2 s3Encryption = AmazonS3EncryptionClientV2Builder.standard()
         .withRegion(Regions.US_WEST_2)
         .withCryptoConfiguration(new CryptoConfigurationV2().withCryptoMode((CryptoMode.StrictAuthenticatedEncryption)))
         .withEncryptionMaterialsProvider(new StaticEncryptionMaterialsProvider(new EncryptionMaterials(secretKey)))
         .build();

s3Encryption.putObject(bucket_name, ENCRYPTED_KEY2, "This is the 2nd content to encrypt");
```

## 经身份验证加密模式
<a name="authenticated-encryption-mode"></a>

使用 `AuthenticatedEncryption` 模式时，在加密期间会应用改进的密钥包装算法。在此模式下解密时，该算法会验证已解密对象的完整性，如果检查失败，则引发异常。有关经身份验证加密模式工作原理的更多详细信息，请参阅博客文章 [Amazon S3 Client-Side Authenticated Encryption](https://aws.amazon.com/blogs/developer/amazon-s3-client-side-authenticated-encryption)。

**注意**  
要使用客户端经身份验证加密，您必须将最新的 [Bouncy Castle jar](https://www.bouncycastle.org/download/bouncy-castle-java/) 文件加入应用程序的类路径中。

要启用此模式，请在 `AuthenticatedEncryption` 方法中指定 `withCryptoConfiguration` 值。

 **代码** 

```
AmazonS3EncryptionV2 s3EncryptionClientV2 = AmazonS3EncryptionClientV2Builder.standard()
         .withRegion(Regions.DEFAULT_REGION)
         .withClientConfiguration(new ClientConfiguration())
         .withCryptoConfiguration(new CryptoConfigurationV2().withCryptoMode(CryptoMode.AuthenticatedEncryption))
         .withEncryptionMaterialsProvider(new StaticEncryptionMaterialsProvider(new EncryptionMaterials(secretKey)))
         .build();

s3EncryptionClientV2.putObject(bucket_name, ENCRYPTED_KEY1, "This is the 1st content to encrypt");
```

# Amazon S3 客户端加密配合 AWS KMS 托管密钥
<a name="examples-crypto-kms"></a>

以下示例使用 [AmazonS3EncryptionClientV2Builder](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/services/s3/AmazonS3EncryptionClientV2Builder.html) 类创建启用客户端加密的 Amazon S3 客户端。配置后，您使用此客户端上传到 Amazon S3 的任何对象都将加密。您使用此客户端从 Amazon S3 获取的任何对象都将自动解密。

**注意**  
以下示例演示如何将 Amazon S3 客户端加密和 AWS 托管密钥配合使用。要了解如何将加密与您自己的密钥配合使用，请参阅 [Amazon S3 客户端加密配合客户端主密钥](examples-crypto-masterkey.md)。

启用客户端 Amazon S3 加密时，您可以从两种加密模式中进行选择：经严格身份验证或经身份验证。以下部分说明了如何启用每种类型。要了解每种模式使用哪种算法，请参阅 [CryptoMode](https://docs.aws.amazon.com/sdk-for-java/v1/reference/com/amazonaws/services/s3/model/CryptoMode.html) 定义。

## 必需的导入
<a name="required-imports"></a>

为这些示例导入以下类。

 **导入**。

```
import com.amazonaws.ClientConfiguration;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.kms.AWSKMS;
import com.amazonaws.services.kms.AWSKMSClientBuilder;
import com.amazonaws.services.kms.model.GenerateDataKeyRequest;
import com.amazonaws.services.kms.model.GenerateDataKeyResult;
import com.amazonaws.services.s3.AmazonS3EncryptionClientV2Builder;
import com.amazonaws.services.s3.AmazonS3EncryptionV2;
import com.amazonaws.services.s3.model.CryptoConfigurationV2;
import com.amazonaws.services.s3.model.CryptoMode;
import com.amazonaws.services.s3.model.EncryptionMaterials;
import com.amazonaws.services.s3.model.KMSEncryptionMaterialsProvider;
```

## 经严格身份验证加密
<a name="strict-authenticated-encryption-kms"></a>

如果未指定 `CryptoMode`，则默认模式为经严格身份验证加密。

要显式启用此模式，请在 `withCryptoConfiguration` 方法中指定 `StrictAuthenticatedEncryption` 值。

**注意**  
要使用客户端经身份验证加密，您必须将最新的 [Bouncy Castle jar](https://www.bouncycastle.org/download/bouncy-castle-java/) 文件加入应用程序的类路径中。

 **代码** 

```
AmazonS3EncryptionV2 s3Encryption = AmazonS3EncryptionClientV2Builder.standard()
         .withRegion(Regions.US_WEST_2)
         .withCryptoConfiguration(new CryptoConfigurationV2().withCryptoMode((CryptoMode.StrictAuthenticatedEncryption)))
         .withEncryptionMaterialsProvider(new KMSEncryptionMaterialsProvider(keyId))
         .build();

s3Encryption.putObject(bucket_name, ENCRYPTED_KEY3, "This is the 3rd content to encrypt with a key created in the {console}");
System.out.println(s3Encryption.getObjectAsString(bucket_name, ENCRYPTED_KEY3));
```

对 `putObject` 加密客户端调用 Amazon S3 方法以上传对象。

 **代码** 

```
s3Encryption.putObject(bucket_name, ENCRYPTED_KEY3, "This is the 3rd content to encrypt with a key created in the {console}");
```

您可以使用同一个客户端检索该对象。此示例调用 `getObjectAsString` 方法以检索存储的字符串。

 **代码** 

```
System.out.println(s3Encryption.getObjectAsString(bucket_name, ENCRYPTED_KEY3));
```

## 经身份验证加密模式
<a name="authenticated-encryption-kms"></a>

使用 `AuthenticatedEncryption` 模式时，在加密期间会应用改进的密钥包装算法。在此模式下解密时，该算法会验证已解密对象的完整性，如果检查失败，则引发异常。有关经身份验证加密模式工作原理的更多详细信息，请参阅博客文章 [Amazon S3 Client-Side Authenticated Encryption](https://aws.amazon.com/blogs/developer/amazon-s3-client-side-authenticated-encryption)。

**注意**  
要使用客户端经身份验证加密，您必须将最新的 [Bouncy Castle jar](https://www.bouncycastle.org/download/bouncy-castle-java/) 文件加入应用程序的类路径中。

要启用此模式，请在 `AuthenticatedEncryption` 方法中指定 `withCryptoConfiguration` 值。

 **代码** 

```
AmazonS3EncryptionV2 s3Encryption = AmazonS3EncryptionClientV2Builder.standard()
         .withRegion(Regions.US_WEST_2)
         .withCryptoConfiguration(new CryptoConfigurationV2().withCryptoMode((CryptoMode.AuthenticatedEncryption)))
         .withEncryptionMaterialsProvider(new KMSEncryptionMaterialsProvider(keyId))
         .build();
```

## 配置 AWS KMS 客户端
<a name="configure-kms"></a>

除非明确指定了 AWS KMS 客户端，否则默认情况下，Amazon S3 加密客户端会创建一个该客户端。

要为这个自动创建的 AWS KMS 客户端设置区域，请设置 `awsKmsRegion`。

 **代码** 

```
Region kmsRegion = Region.getRegion(Regions.AP_NORTHEAST_1);

AmazonS3EncryptionV2 s3Encryption = AmazonS3EncryptionClientV2Builder.standard()
        .withRegion(Regions.US_WEST_2)
        .withCryptoConfiguration(new CryptoConfigurationV2().withAwsKmsRegion(kmsRegion))
        .withEncryptionMaterialsProvider(new KMSEncryptionMaterialsProvider(keyId))
        .build();
```

或者，您可以使用自己的 AWS KMS 客户端来初始化加密客户端。

 **代码** 

```
AWSKMS kmsClient = AWSKMSClientBuilder.standard()
        .withRegion(Regions.US_WEST_2);
        .build();

AmazonS3EncryptionV2 s3Encryption = AmazonS3EncryptionClientV2Builder.standard()
        .withRegion(Regions.US_WEST_2)
        .withKmsClient(kmsClient)
        .withCryptoConfiguration(new CryptoConfigurationV2().withCryptoMode((CryptoMode.AuthenticatedEncryption)))
        .withEncryptionMaterialsProvider(new KMSEncryptionMaterialsProvider(keyId))
        .build();
```