

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

# 使用 Amazon S3 代码示例 适用于 C\$1\$1 的 AWS SDK
<a name="examples-s3"></a>

[Amazon S3](https://aws.amazon.com/s3) 是专为从任意位置存储和检索任意数量的数据而构建的对象存储。提供了多个类来与 Amazon S3 接口。 适用于 C\$1\$1 的 AWS SDK 

**注意**  
本指南中仅提供了演示某些技术所需的代码，但[完整的示例代码可在上找到 GitHub](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/cpp)。 GitHub 您可以下载单个源文件，也可以在本地克隆存储库以获取、构建和运行所有示例。
+ [https://docs.aws.amazon.com/sdk-for-cpp/latest/api/aws-cpp-sdk-s3/html/class_aws_1_1_s3_1_1_s3_client.html](https://docs.aws.amazon.com/sdk-for-cpp/latest/api/aws-cpp-sdk-s3/html/class_aws_1_1_s3_1_1_s3_client.html) 类 

  `S3Client` 库是一个功能齐全的 Amazon S3 接口。

  本集中的`list_buckets_disabling_dns_cache.cpp`示例专门针对在 CURL 开启的情况下使用 Linux/Mac （尽管可以修改为在 Windows 上运行）。如果你使用的是 Windows，请在生成项目`list_buckets_disabling_dns_cache.cpp`之前删除该文件，因为它依赖于 Linux 的 curl HttpClient 。

  使用 `S3Client` 的示例代码位于 Github 上的 [`s3` 文件夹](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/cpp/example_code/s3)中。有关此示例集演示的函数的完整列表，请参阅 Github 上的[自述文件](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/cpp/example_code/s3/README.md)。

  本指南更详细地介绍了 `s3` 示例集的各个部分：
  + [创建、列出和删除存储桶](examples-s3-buckets.md)
  + [在对象上的操作](examples-s3-objects.md) – 上传和下载数据对象
  + [管理 Amazon S3 访问权限](examples-s3-access-permissions.md)
  + [使用存储桶策略管理对 Amazon S3 存储桶的访问](examples-s3-bucket-policies.md)
  + [将 Amazon S3 存储桶配置为网站](examples-s3-website-configuration.md)
+ [https://docs.aws.amazon.com/sdk-for-cpp/latest/api/aws-cpp-sdk-s3-crt/html/class_aws_1_1_s3_crt_1_1_s3_crt_client.html](https://docs.aws.amazon.com/sdk-for-cpp/latest/api/aws-cpp-sdk-s3-crt/html/class_aws_1_1_s3_crt_1_1_s3_crt_client.html) 类 

  `S3CrtClient` 在 SDK 的 1.9 版本中被引入。`S3CrtClient` 为 Amazon S3 的 GET（下载）和 PUT（上传）操作提供高吞吐量。`S3CrtClient`是在 AWS 公共运行时 (CRT) 库的顶部实现的。

  使用 `S3CrtClient` 的示例代码位于 Github 上的 [`s3-crt` 文件夹](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/cpp/example_code/s3-crt)中。有关此示例集演示的函数的完整列表，请参阅 Github 上的[自述文件](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/cpp/example_code/s3-crt/README.md)。
  + [使用 `S3CrtClient` 执行 Amazon S3 操作](examples-s3-crt.md)
+ [https://docs.aws.amazon.com/sdk-for-cpp/latest/api/aws-cpp-sdk-transfer/html/class_aws_1_1_transfer_1_1_transfer_manager.html](https://docs.aws.amazon.com/sdk-for-cpp/latest/api/aws-cpp-sdk-transfer/html/class_aws_1_1_transfer_1_1_transfer_manager.html) 类 

  `TransferManager` 是一项完全托管式服务，支持通过文件传输协议（FTP）、基于 SSL 的文件传输协议（FTPS）或 Secure Shell（SSH）文件传输协议（SFTP），直接向 Amazon S3 中传入文件以及从中传出文件。

  使用 `TransferManager` 的示例代码位于 Github 上的 [`transfer-manager` 文件夹](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/cpp/example_code/transfer-manager)中。有关此示例集演示的函数的完整列表，请参阅 Github 上的[自述文件](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/cpp/example_code/transfer-manager/README.md)。
  + [用 TransferManager 于 Amazon S3 操作](examples-s3-transfermanager.md)

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

Amazon Simple Storage Service（Amazon S3）中的每个对象**或文件都包含在一个**存储桶中，该存储桶代表一个对象文件夹。每个存储桶都有一个在 AWS 内全局唯一的名称。有关更多信息，请参阅《Amazon Simple Storage Service 用户指南》中的[使用 Amazon S3 存储桶](https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingBucket.html)。

## 先决条件
<a name="codeExamplePrereq"></a>

在开始之前，建议您先阅读[开始使用适用于 C\$1\$1 的 AWS SDK](getting-started.md)。

下载示例代码并按[代码示例入门](getting-started-code-examples.md)中所述构建解决方案。

要运行这些示例，您的代码用于发出请求的用户配置文件必须在 AWS 中具有适当的权限（用于服务和操作）。有关更多信息，请参阅[提供 AWS 凭证](credentials.md)。

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

要运行 `list_buckets` 示例，请在命令提示符下，导航至构建系统生成可执行文件的文件夹。运行可执行文件，例如 `run_list_buckets`（完整的可执行文件名因操作系统而异）。输出会列出您账户的存储桶（如果有），如果您没有任何存储桶，则会显示一个空列表。

`list_buckets.cpp` 中有两种方法：
+ `main()` 调用 `ListBuckets()`。
+ `ListBuckets()` 使用 SDK 查询您的存储桶。

`S3Client` 对象会调用 SDK 的 `ListBuckets()` 方法。如果成功，该方法将返回一个包含 `ListBucketResult` 对象的 `ListBucketOutcome` 对象。`ListBucketResult` 对象会调用 `GetBuckets()` 方法以获取包含您账户中每个 Amazon S3 存储桶信息的 `Bucket` 对象列表。

 **代码** 

```
bool AwsDoc::S3::listBuckets(const Aws::S3::S3ClientConfiguration &clientConfig) {
    Aws::S3::S3Client client(clientConfig);

    auto outcome = client.ListBuckets();

    bool result = true;
    if (!outcome.IsSuccess()) {
        std::cerr << "Failed with error: " << outcome.GetError() << std::endl;
        result = false;
    } else {
        std::cout << "Found " << outcome.GetResult().GetBuckets().size() << " buckets\n";
        for (auto &&b: outcome.GetResult().GetBuckets()) {
            std::cout << b.GetName() << std::endl;
        }
    }

    return result;
}
```

请参阅 Github 上的完整 [list\$1buckets 示例](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/cpp/example_code/s3/list_buckets.cpp)。

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



要运行 `create_bucket` 示例，请在命令提示符下，导航至构建系统生成可执行文件的文件夹。运行可执行文件，例如 `run_create_bucket`（完整的可执行文件名因操作系统而异）。该代码会在您的账户下创建一个空存储桶，然后显示请求成功还是失败。

`create_bucket.cpp` 中有两种方法：
+ `main()` 调用 `CreateBucket()`。在 `main()` 中，您需要使用 `enum` 将 AWS 区域 更改为账户所在区域。您可以登录[AWS 管理控制台](https://console.aws.amazon.com/)查看账户所在区域，然后在右上角找到该区域。
+ `CreateBucket()` 使用 SDK 创建存储桶。



`S3Client` 对象调用 SDK 的 `CreateBucket()` 方法，传入带有存储桶名称的 `CreateBucketRequest`。默认情况下，存储桶在 *us-east-1*（弗吉尼亚州北部）区域创建。如果您的区域不是 *us-east-1*，则代码会设置存储桶约束，以确保在您所在地区创建存储桶。

 **代码** 

```
bool AwsDoc::S3::createBucket(const Aws::String &bucketName,
                              const Aws::S3::S3ClientConfiguration &clientConfig) {
    Aws::S3::S3Client client(clientConfig);
    Aws::S3::Model::CreateBucketRequest request;
    request.SetBucket(bucketName);

    if (clientConfig.region != "us-east-1") {
        Aws::S3::Model::CreateBucketConfiguration createBucketConfig;
        createBucketConfig.SetLocationConstraint(
                Aws::S3::Model::BucketLocationConstraintMapper::GetBucketLocationConstraintForName(
                        clientConfig.region));
        request.SetCreateBucketConfiguration(createBucketConfig);
    }

    Aws::S3::Model::CreateBucketOutcome outcome = client.CreateBucket(request);
    if (!outcome.IsSuccess()) {
        auto err = outcome.GetError();
        std::cerr << "Error: createBucket: " <<
                  err.GetExceptionName() << ": " << err.GetMessage() << std::endl;
    } else {
        std::cout << "Created bucket " << bucketName <<
                  " in the specified AWS Region." << std::endl;
    }

    return outcome.IsSuccess();
}
```

请参阅 Github 上的完整 [create\$1buckets 示例](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/cpp/example_code/s3/create_bucket.cpp)。

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



要运行 `delete_bucket` 示例，请在命令提示符下，导航至构建系统生成可执行文件的文件夹。运行可执行文件，例如 `run_delete_bucket`（完整的可执行文件名因操作系统而异）。此代码会删除您账户中指定的存储桶，然后显示请求成功还是失败。

在 `delete_bucket.cpp` 中，有两种方法。
+ `main()` 调用 `DeleteBucket()`。在 `main()` 中，您需要使用 `enum` 将 AWS 区域 更改为账户所在区域。您还需要将 `bucket_name` 更改为要删除的存储桶的名称。
+ `DeleteBucket()` 使用 SDK 删除存储桶。



`S3Client` 对象使用 SDK 的 `DeleteBucket()` 方法，并传入一个带有要删除的存储桶名称的 `DeleteBucketRequest` 对象。存储桶必须为空才能成功。

 **代码**

```
bool AwsDoc::S3::deleteBucket(const Aws::String &bucketName,
                              const Aws::S3::S3ClientConfiguration &clientConfig) {

    Aws::S3::S3Client client(clientConfig);

    Aws::S3::Model::DeleteBucketRequest request;
    request.SetBucket(bucketName);

    Aws::S3::Model::DeleteBucketOutcome outcome =
            client.DeleteBucket(request);

    if (!outcome.IsSuccess()) {
        const Aws::S3::S3Error &err = outcome.GetError();
        std::cerr << "Error: deleteBucket: " <<
                  err.GetExceptionName() << ": " << err.GetMessage() << std::endl;
    } else {
        std::cout << "The bucket was deleted" << std::endl;
    }

    return outcome.IsSuccess();
}
```

请参阅 Github 上的完整 [delete\$1bucket 示例](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/cpp/example_code/s3/delete_bucket.cpp)。

# 在对象上的操作
<a name="examples-s3-objects"></a>

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

## 先决条件
<a name="codeExamplePrereq"></a>

在开始之前，建议您先阅读[开始使用 适用于 C\$1\$1 的 AWS SDK](getting-started.md)。

下载示例代码并按[代码示例入门](getting-started-code-examples.md)中所述构建解决方案。

要运行这些示例，您的代码用于发出请求的用户配置文件必须具有适当的权限 AWS （适用于服务和操作）。有关更多信息，请参阅[提供 AWS 凭证](credentials.md)。

## 将文件上传到存储桶
<a name="upload-object"></a>

使用 `S3Client` 对象的 `PutObject` 函数，并为其提供存储桶名称、键名称和要上传的文件。`Aws::FStream` 用于将本地文件的内容上传到存储桶。存储桶必须存在，否则将出现错误。

有关异步上传对象的示例，请参阅[异步编程使用 适用于 C\$1\$1 的 AWS SDK](async-methods.md)

 **代码** 

```
bool AwsDoc::S3::putObject(const Aws::String &bucketName,
                           const Aws::String &fileName,
                           const Aws::S3::S3ClientConfiguration &clientConfig) {
    Aws::S3::S3Client s3Client(clientConfig);

    Aws::S3::Model::PutObjectRequest request;
    request.SetBucket(bucketName);
    //We are using the name of the file as the key for the object in the bucket.
    //However, this is just a string and can be set according to your retrieval needs.
    request.SetKey(fileName);

    std::shared_ptr<Aws::IOStream> inputData =
            Aws::MakeShared<Aws::FStream>("SampleAllocationTag",
                                          fileName.c_str(),
                                          std::ios_base::in | std::ios_base::binary);

    if (!*inputData) {
        std::cerr << "Error unable to read file " << fileName << std::endl;
        return false;
    }

    request.SetBody(inputData);

    Aws::S3::Model::PutObjectOutcome outcome =
            s3Client.PutObject(request);

    if (!outcome.IsSuccess()) {
        std::cerr << "Error: putObject: " <<
                  outcome.GetError().GetMessage() << std::endl;
    } else {
        std::cout << "Added object '" << fileName << "' to bucket '"
                  << bucketName << "'.";
    }

    return outcome.IsSuccess();
}
```

请参阅 [Github](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/cpp/example_code/s3/put_object.cpp) 上的完整示例。

## 将字符串上传到存储桶
<a name="upload-object-string"></a>

使用 `S3Client` 对象的 `PutObject` 函数，并为其提供存储桶名称、键名称和要上传的文件。存储桶必须存在，否则将出现错误。此示例与前一个示例的不同之处在于，它使用 `Aws::StringStream` 将内存中的字符串数据对象直接上传到存储桶。

有关异步上传对象的示例，请参阅[异步编程使用 适用于 C\$1\$1 的 AWS SDK](async-methods.md)

 **代码** 

```
bool AwsDoc::S3::putObjectBuffer(const Aws::String &bucketName,
                                 const Aws::String &objectName,
                                 const std::string &objectContent,
                                 const Aws::S3::S3ClientConfiguration &clientConfig) {
    Aws::S3::S3Client s3Client(clientConfig);

    Aws::S3::Model::PutObjectRequest request;
    request.SetBucket(bucketName);
    request.SetKey(objectName);

    const std::shared_ptr<Aws::IOStream> inputData =
            Aws::MakeShared<Aws::StringStream>("");
    *inputData << objectContent.c_str();

    request.SetBody(inputData);

    Aws::S3::Model::PutObjectOutcome outcome = s3Client.PutObject(request);

    if (!outcome.IsSuccess()) {
        std::cerr << "Error: putObjectBuffer: " <<
                  outcome.GetError().GetMessage() << std::endl;
    } else {
        std::cout << "Success: Object '" << objectName << "' with content '"
                  << objectContent << "' uploaded to bucket '" << bucketName << "'.";
    }

    return outcome.IsSuccess();
}
```

请参阅 [Github](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/cpp/example_code/s3/put_object_buffer.cpp) 上的完整示例。

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

要获取存储桶中的对象列表，请使用 `S3Client` 对象 `ListObjects` 函数。向其提供一个 `ListObjectsRequest` 对象，该对象需设置要列出内容的存储桶名称。

`ListObjects` 函数返回一个 `ListObjectsOutcome` 对象，您可以使用该对象以 `Object` 实例的形式获取对象列表。

 **代码** 

```
bool AwsDoc::S3::listObjects(const Aws::String &bucketName,
                             Aws::Vector<Aws::String> &keysResult,
                             const Aws::S3::S3ClientConfiguration &clientConfig) {
    Aws::S3::S3Client s3Client(clientConfig);

    Aws::S3::Model::ListObjectsV2Request request;
    request.WithBucket(bucketName);

    Aws::String continuationToken; // Used for pagination.
    Aws::Vector<Aws::S3::Model::Object> allObjects;

    do {
        if (!continuationToken.empty()) {
            request.SetContinuationToken(continuationToken);
        }

        auto outcome = s3Client.ListObjectsV2(request);

        if (!outcome.IsSuccess()) {
            std::cerr << "Error: listObjects: " <<
                      outcome.GetError().GetMessage() << std::endl;
            return false;
        } else {
            Aws::Vector<Aws::S3::Model::Object> objects =
                    outcome.GetResult().GetContents();

            allObjects.insert(allObjects.end(), objects.begin(), objects.end());
            continuationToken = outcome.GetResult().GetNextContinuationToken();
        }
    } while (!continuationToken.empty());

    std::cout << allObjects.size() << " object(s) found:" << std::endl;

    for (const auto &object: allObjects) {
        std::cout << "  " << object.GetKey() << std::endl;
        keysResult.push_back(object.GetKey());
    }

    return true;
}
```

请参阅 [Github](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/cpp/example_code/s3/list_objects.cpp) 上的完整示例。

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

使用 `S3Client` 对象的 `GetObject` 函数，并向其传递一个 `GetObjectRequest` 对象，该对象需设置要下载的存储桶名称和对象键。`GetObject` 会返回一个 [https://docs.aws.amazon.com/sdk-for-cpp/latest/api/aws-cpp-sdk-s3/html/namespace_aws_1_1_s3_1_1_model.html#a6e16a7b25e8c7547934968a538a15272](https://docs.aws.amazon.com/sdk-for-cpp/latest/api/aws-cpp-sdk-s3/html/namespace_aws_1_1_s3_1_1_model.html#a6e16a7b25e8c7547934968a538a15272) 对象，该对象包含一个 [https://docs.aws.amazon.com/sdk-for-cpp/latest/api/aws-cpp-sdk-s3/html/class_aws_1_1_s3_1_1_model_1_1_get_object_result.html](https://docs.aws.amazon.com/sdk-for-cpp/latest/api/aws-cpp-sdk-s3/html/class_aws_1_1_s3_1_1_model_1_1_get_object_result.html) 和一个 [https://docs.aws.amazon.com/sdk-for-cpp/latest/api/aws-cpp-sdk-s3/html/class_aws_1_1_s3_1_1_s3_error.html](https://docs.aws.amazon.com/sdk-for-cpp/latest/api/aws-cpp-sdk-s3/html/class_aws_1_1_s3_1_1_s3_error.html)。`GetObjectResult` 可用于访问 S3 对象的数据。

以下示例从 Amazon S3 下载对象。对象内容存储在局部变量中，内容的第一行将输出到控制台。

 **代码** 

```
bool AwsDoc::S3::getObject(const Aws::String &objectKey,
                           const Aws::String &fromBucket,
                           const Aws::S3::S3ClientConfiguration &clientConfig) {
    Aws::S3::S3Client client(clientConfig);

    Aws::S3::Model::GetObjectRequest request;
    request.SetBucket(fromBucket);
    request.SetKey(objectKey);

    Aws::S3::Model::GetObjectOutcome outcome =
            client.GetObject(request);

    if (!outcome.IsSuccess()) {
        const Aws::S3::S3Error &err = outcome.GetError();
        std::cerr << "Error: getObject: " <<
                  err.GetExceptionName() << ": " << err.GetMessage() << std::endl;
    } else {
        std::cout << "Successfully retrieved '" << objectKey << "' from '"
                  << fromBucket << "'." << std::endl;
    }

    return outcome.IsSuccess();
}
```

请参阅 [Github](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/cpp/example_code/s3/get_object.cpp) 上的完整示例。

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

使用 `S3Client` 对象的 `DeleteObject` 函数，并向其传递一个 `DeleteObjectRequest` 对象，该对象需设置要删除的存储桶名称和对象键。*指定的存储桶和对象键必须存在，否则将出现错误*。

 **代码** 

```
bool AwsDoc::S3::deleteObject(const Aws::String &objectKey,
                              const Aws::String &fromBucket,
                              const Aws::S3::S3ClientConfiguration &clientConfig) {
    Aws::S3::S3Client client(clientConfig);
    Aws::S3::Model::DeleteObjectRequest request;

    request.WithKey(objectKey)
            .WithBucket(fromBucket);

    Aws::S3::Model::DeleteObjectOutcome outcome =
            client.DeleteObject(request);

    if (!outcome.IsSuccess()) {
        auto err = outcome.GetError();
        std::cerr << "Error: deleteObject: " <<
                  err.GetExceptionName() << ": " << err.GetMessage() << std::endl;
    } else {
        std::cout << "Successfully deleted the object." << std::endl;
    }

    return outcome.IsSuccess();
}
```

请参阅 [Github](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/cpp/example_code/s3/delete_object.cpp) 上的完整示例。

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

Amazon S3 存储桶或对象的访问权限在访问控制列表（ACL）中定义。ACL 指定了 bucket/object 的所有者和授权列表。每个授权项都指定一名用户（或被授权者）以及该用户访问存储桶/对象的权限，例如读取或写入权限。

## 先决条件
<a name="codeExamplePrereq"></a>

在开始之前，建议您先阅读[开始使用 适用于 C\$1\$1 的 AWS SDK](getting-started.md)。

下载示例代码并按[代码示例入门](getting-started-code-examples.md)中所述构建解决方案。

要运行这些示例，您的代码用于发出请求的用户配置文件必须具有适当的权限 AWS （适用于服务和操作）。有关更多信息，请参阅[提供 AWS 凭证](credentials.md)。

## 管理对象的访问控制列表
<a name="manage-an-object-s-access-control-list"></a>

可以通过调用 `S3Client` 方法 `GetObjectAcl` 来检索对象的访问控制列表。该方法接受对象及其存储桶的名称。返回值包括 ACL 的 `Owner` 及 `Grants` 列表。

```
bool AwsDoc::S3::getObjectAcl(const Aws::String &bucketName,
                              const Aws::String &objectKey,
                              const Aws::S3::S3ClientConfiguration &clientConfig) {
    Aws::S3::S3Client s3Client(clientConfig);

    Aws::S3::Model::GetObjectAclRequest request;
    request.SetBucket(bucketName);
    request.SetKey(objectKey);

    Aws::S3::Model::GetObjectAclOutcome outcome =
            s3Client.GetObjectAcl(request);

    if (!outcome.IsSuccess()) {
        const Aws::S3::S3Error &err = outcome.GetError();
        std::cerr << "Error: getObjectAcl: "
                  << err.GetExceptionName() << ": " << err.GetMessage() << std::endl;
    } else {
        Aws::Vector<Aws::S3::Model::Grant> grants =
                outcome.GetResult().GetGrants();

        for (auto it = grants.begin(); it != grants.end(); it++) {
            std::cout << "For object " << objectKey << ": "
                      << std::endl << std::endl;

            Aws::S3::Model::Grant grant = *it;
            Aws::S3::Model::Grantee grantee = grant.GetGrantee();

            if (grantee.TypeHasBeenSet()) {
                std::cout << "Type:          "
                          << getGranteeTypeString(grantee.GetType()) << std::endl;
            }

            if (grantee.DisplayNameHasBeenSet()) {
                std::cout << "Display name:  "
                          << grantee.GetDisplayName() << std::endl;
            }

            if (grantee.EmailAddressHasBeenSet()) {
                std::cout << "Email address: "
                          << grantee.GetEmailAddress() << std::endl;
            }

            if (grantee.IDHasBeenSet()) {
                std::cout << "ID:            "
                          << grantee.GetID() << std::endl;
            }

            if (grantee.URIHasBeenSet()) {
                std::cout << "URI:           "
                          << grantee.GetURI() << std::endl;
            }

            std::cout << "Permission:    " <<
                      getPermissionString(grant.GetPermission()) <<
                      std::endl << std::endl;
        }
    }

    return outcome.IsSuccess();
}

//! Routine which converts a built-in type enumeration to a human-readable string.
/*!
 \param type: Type enumeration.
 \return String: Human-readable string
*/
Aws::String getGranteeTypeString(const Aws::S3::Model::Type &type) {
    switch (type) {
        case Aws::S3::Model::Type::AmazonCustomerByEmail:
            return "Email address of an AWS account";
        case Aws::S3::Model::Type::CanonicalUser:
            return "Canonical user ID of an AWS account";
        case Aws::S3::Model::Type::Group:
            return "Predefined Amazon S3 group";
        case Aws::S3::Model::Type::NOT_SET:
            return "Not set";
        default:
            return "Type unknown";
    }
}

//! Routine which converts a built-in type enumeration to a human-readable string.
/*!
 \param permission: Permission enumeration.
 \return String: Human-readable string
*/
Aws::String getPermissionString(const Aws::S3::Model::Permission &permission) {
    switch (permission) {
        case Aws::S3::Model::Permission::FULL_CONTROL:
            return "Can read this object's data and its metadata, "
                   "and read/write this object's permissions";
        case Aws::S3::Model::Permission::NOT_SET:
            return "Permission not set";
        case Aws::S3::Model::Permission::READ:
            return "Can read this object's data and its metadata";
        case Aws::S3::Model::Permission::READ_ACP:
            return "Can read this object's permissions";
            // case Aws::S3::Model::Permission::WRITE // Not applicable.
        case Aws::S3::Model::Permission::WRITE_ACP:
            return "Can write this object's permissions";
        default:
            return "Permission unknown";
    }
}
```

可以通过创建新 ACL 或更改当前 ACL 中指定的授权项来修改 ACL。通过将更新后的 ACL 传递给 `PutObjectAcl` 方法，它将成为新的当前 ACL。

以下代码使用 `GetObjectAcl` 检索到的 ACL，并为其添加新的授权项。用户或被授权者被授予该对象的读取权限。修改后的 ACL 将传递给 `PutObjectAcl`，使其成为新的当前 ACL。

```
bool AwsDoc::S3::putObjectAcl(const Aws::String &bucketName, const Aws::String &objectKey, const Aws::String &ownerID,
                              const Aws::String &granteePermission, const Aws::String &granteeType,
                              const Aws::String &granteeID, const Aws::String &granteeEmailAddress,
                              const Aws::String &granteeURI, const Aws::S3::S3ClientConfiguration &clientConfig) {
    Aws::S3::S3Client s3Client(clientConfig);

    Aws::S3::Model::Owner owner;
    owner.SetID(ownerID);

    Aws::S3::Model::Grantee grantee;
    grantee.SetType(setGranteeType(granteeType));

    if (!granteeEmailAddress.empty()) {
        grantee.SetEmailAddress(granteeEmailAddress);
    }

    if (!granteeID.empty()) {
        grantee.SetID(granteeID);
    }

    if (!granteeURI.empty()) {
        grantee.SetURI(granteeURI);
    }

    Aws::S3::Model::Grant grant;
    grant.SetGrantee(grantee);
    grant.SetPermission(setGranteePermission(granteePermission));

    Aws::Vector<Aws::S3::Model::Grant> grants;
    grants.push_back(grant);

    Aws::S3::Model::AccessControlPolicy acp;
    acp.SetOwner(owner);
    acp.SetGrants(grants);

    Aws::S3::Model::PutObjectAclRequest request;
    request.SetAccessControlPolicy(acp);
    request.SetBucket(bucketName);
    request.SetKey(objectKey);

    Aws::S3::Model::PutObjectAclOutcome outcome =
            s3Client.PutObjectAcl(request);

    if (!outcome.IsSuccess()) {
        auto error = outcome.GetError();
        std::cerr << "Error: putObjectAcl: " << error.GetExceptionName()
                  << " - " << error.GetMessage() << std::endl;
    } else {
        std::cout << "Successfully added an ACL to the object '" << objectKey
                  << "' in the bucket '" << bucketName << "'." << std::endl;
    }

    return outcome.IsSuccess();
}

//! Routine which converts a human-readable string to a built-in type enumeration.
/*!
 \param access: Human readable string.
 \return Permission: Permission enumeration.
*/
Aws::S3::Model::Permission setGranteePermission(const Aws::String &access) {
    if (access == "FULL_CONTROL")
        return Aws::S3::Model::Permission::FULL_CONTROL;
    if (access == "WRITE")
        return Aws::S3::Model::Permission::WRITE;
    if (access == "READ")
        return Aws::S3::Model::Permission::READ;
    if (access == "WRITE_ACP")
        return Aws::S3::Model::Permission::WRITE_ACP;
    if (access == "READ_ACP")
        return Aws::S3::Model::Permission::READ_ACP;
    return Aws::S3::Model::Permission::NOT_SET;
}

//! Routine which converts a human-readable string to a built-in type enumeration.
/*!
 \param type: Human readable string.
 \return Type: Type enumeration.
*/
Aws::S3::Model::Type setGranteeType(const Aws::String &type) {
    if (type == "Amazon customer by email")
        return Aws::S3::Model::Type::AmazonCustomerByEmail;
    if (type == "Canonical user")
        return Aws::S3::Model::Type::CanonicalUser;
    if (type == "Group")
        return Aws::S3::Model::Type::Group;
    return Aws::S3::Model::Type::NOT_SET;
}
```

请参阅 [Github](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/cpp/example_code/s3/get_put_object_acl.cpp) 上的完整示例。

## 管理存储桶的访问控制列表
<a name="manage-a-bucket-s-access-control-list"></a>

大多数情况下，设置存储桶访问权限的首选方法是定义存储桶策略。不过，存储桶也支持访问控制列表，供需要使用它们的用户使用。

存储桶的访问控制列表管理方式与对象的访问控制列表管理方式完全相同。`GetBucketAcl` 方法检索存储桶的当前 ACL，`PutBucketAcl` 对存储桶应用新的 ACL。

以下代码演示如何获取和设置存储桶 ACL。

```
//! Routine which demonstrates setting the ACL for an S3 bucket.
/*!
  \param bucketName: Name of a bucket.
  \param ownerID: The canonical ID of the bucket owner.
   See https://docs.aws.amazon.com/AmazonS3/latest/userguide/finding-canonical-user-id.html for more information.
  \param granteePermission: The access level to enable for the grantee.
  \param granteeType: The type of grantee.
  \param granteeID: The canonical ID of the grantee.
  \param granteeEmailAddress: The email address associated with the grantee's AWS account.
  \param granteeURI: The URI of a built-in access group.
  \param clientConfig: Aws client configuration.
  \return bool: Function succeeded.
*/

bool AwsDoc::S3::getPutBucketAcl(const Aws::String &bucketName,
                                 const Aws::String &ownerID,
                                 const Aws::String &granteePermission,
                                 const Aws::String &granteeType,
                                 const Aws::String &granteeID,
                                 const Aws::String &granteeEmailAddress,
                                 const Aws::String &granteeURI,
                                 const Aws::S3::S3ClientConfiguration &clientConfig) {
    bool result = ::putBucketAcl(bucketName, ownerID, granteePermission, granteeType,
                                 granteeID,
                                 granteeEmailAddress,
                                 granteeURI,
                                 clientConfig);
    if (result) {
        result = ::getBucketAcl(bucketName, clientConfig);
    }

    return result;
}

//! Routine which demonstrates setting the ACL for an S3 bucket.
/*!
  \param bucketName: Name of from bucket.
  \param ownerID: The canonical ID of the bucket owner.
   See https://docs.aws.amazon.com/AmazonS3/latest/userguide/finding-canonical-user-id.html for more information.
  \param granteePermission: The access level to enable for the grantee.
  \param granteeType: The type of grantee.
  \param granteeID: The canonical ID of the grantee.
  \param granteeEmailAddress: The email address associated with the grantee's AWS account.
  \param granteeURI: The URI of a built-in access group.
  \param clientConfig: Aws client configuration.
  \return bool: Function succeeded.
*/

bool putBucketAcl(const Aws::String &bucketName,
                  const Aws::String &ownerID,
                  const Aws::String &granteePermission,
                  const Aws::String &granteeType,
                  const Aws::String &granteeID,
                  const Aws::String &granteeEmailAddress,
                  const Aws::String &granteeURI,
                  const Aws::S3::S3ClientConfiguration &clientConfig) {
    Aws::S3::S3Client s3Client(clientConfig);

    Aws::S3::Model::Owner owner;
    owner.SetID(ownerID);

    Aws::S3::Model::Grantee grantee;
    grantee.SetType(setGranteeType(granteeType));

    if (!granteeEmailAddress.empty()) {
        grantee.SetEmailAddress(granteeEmailAddress);
    }

    if (!granteeID.empty()) {
        grantee.SetID(granteeID);
    }

    if (!granteeURI.empty()) {
        grantee.SetURI(granteeURI);
    }

    Aws::S3::Model::Grant grant;
    grant.SetGrantee(grantee);
    grant.SetPermission(setGranteePermission(granteePermission));

    Aws::Vector<Aws::S3::Model::Grant> grants;
    grants.push_back(grant);

    Aws::S3::Model::AccessControlPolicy acp;
    acp.SetOwner(owner);
    acp.SetGrants(grants);

    Aws::S3::Model::PutBucketAclRequest request;
    request.SetAccessControlPolicy(acp);
    request.SetBucket(bucketName);

    Aws::S3::Model::PutBucketAclOutcome outcome =
            s3Client.PutBucketAcl(request);

    if (!outcome.IsSuccess()) {
        const Aws::S3::S3Error &error = outcome.GetError();

        std::cerr << "Error: putBucketAcl: " << error.GetExceptionName()
                  << " - " << error.GetMessage() << std::endl;
    } else {
        std::cout << "Successfully added an ACL to the bucket '" << bucketName
                  << "'." << std::endl;
    }

    return outcome.IsSuccess();
}

//! Routine which demonstrates getting the ACL for an S3 bucket.
/*!
  \param bucketName: Name of the s3 bucket.
  \param clientConfig: Aws client configuration.
  \return bool: Function succeeded.
*/
bool getBucketAcl(const Aws::String &bucketName,
                  const Aws::S3::S3ClientConfiguration &clientConfig) {
    Aws::S3::S3Client s3Client(clientConfig);

    Aws::S3::Model::GetBucketAclRequest request;
    request.SetBucket(bucketName);

    Aws::S3::Model::GetBucketAclOutcome outcome =
            s3Client.GetBucketAcl(request);

    if (!outcome.IsSuccess()) {
        const Aws::S3::S3Error &err = outcome.GetError();
        std::cerr << "Error: getBucketAcl: "
                  << err.GetExceptionName() << ": " << err.GetMessage() << std::endl;
    } else {
        const Aws::Vector<Aws::S3::Model::Grant> &grants =
                outcome.GetResult().GetGrants();

        for (const Aws::S3::Model::Grant &grant: grants) {
            const Aws::S3::Model::Grantee &grantee = grant.GetGrantee();

            std::cout << "For bucket " << bucketName << ": "
                      << std::endl << std::endl;

            if (grantee.TypeHasBeenSet()) {
                std::cout << "Type:          "
                          << getGranteeTypeString(grantee.GetType()) << std::endl;
            }

            if (grantee.DisplayNameHasBeenSet()) {
                std::cout << "Display name:  "
                          << grantee.GetDisplayName() << std::endl;
            }

            if (grantee.EmailAddressHasBeenSet()) {
                std::cout << "Email address: "
                          << grantee.GetEmailAddress() << std::endl;
            }

            if (grantee.IDHasBeenSet()) {
                std::cout << "ID:            "
                          << grantee.GetID() << std::endl;
            }

            if (grantee.URIHasBeenSet()) {
                std::cout << "URI:           "
                          << grantee.GetURI() << std::endl;
            }

            std::cout << "Permission:    " <<
                      getPermissionString(grant.GetPermission()) <<
                      std::endl << std::endl;
        }
    }

    return outcome.IsSuccess();
}

//! Routine which converts a built-in type enumeration to a human-readable string.
/*!
 \param permission: Permission enumeration.
 \return String: Human-readable string.
*/

Aws::String getPermissionString(const Aws::S3::Model::Permission &permission) {
    switch (permission) {
        case Aws::S3::Model::Permission::FULL_CONTROL:
            return "Can list objects in this bucket, create/overwrite/delete "
                   "objects in this bucket, and read/write this "
                   "bucket's permissions";
        case Aws::S3::Model::Permission::NOT_SET:
            return "Permission not set";
        case Aws::S3::Model::Permission::READ:
            return "Can list objects in this bucket";
        case Aws::S3::Model::Permission::READ_ACP:
            return "Can read this bucket's permissions";
        case Aws::S3::Model::Permission::WRITE:
            return "Can create, overwrite, and delete objects in this bucket";
        case Aws::S3::Model::Permission::WRITE_ACP:
            return "Can write this bucket's permissions";
        default:
            return "Permission unknown";
    }
}

//! Routine which converts a human-readable string to a built-in type enumeration
/*!
 \param access: Human readable string.
 \return Permission: Permission enumeration.
*/
Aws::S3::Model::Permission setGranteePermission(const Aws::String &access) {
    if (access == "FULL_CONTROL")
        return Aws::S3::Model::Permission::FULL_CONTROL;
    if (access == "WRITE")
        return Aws::S3::Model::Permission::WRITE;
    if (access == "READ")
        return Aws::S3::Model::Permission::READ;
    if (access == "WRITE_ACP")
        return Aws::S3::Model::Permission::WRITE_ACP;
    if (access == "READ_ACP")
        return Aws::S3::Model::Permission::READ_ACP;
    return Aws::S3::Model::Permission::NOT_SET;
}

//! Routine which converts a built-in type enumeration to a human-readable string.
/*!
 \param type: Type enumeration.
 \return bool: Human-readable string.
*/
Aws::String getGranteeTypeString(const Aws::S3::Model::Type &type) {
    switch (type) {
        case Aws::S3::Model::Type::AmazonCustomerByEmail:
            return "Email address of an AWS account";
        case Aws::S3::Model::Type::CanonicalUser:
            return "Canonical user ID of an AWS account";
        case Aws::S3::Model::Type::Group:
            return "Predefined Amazon S3 group";
        case Aws::S3::Model::Type::NOT_SET:
            return "Not set";
        default:
            return "Type unknown";
    }
}

Aws::S3::Model::Type setGranteeType(const Aws::String &type) {
    if (type == "Amazon customer by email")
        return Aws::S3::Model::Type::AmazonCustomerByEmail;
    if (type == "Canonical user")
        return Aws::S3::Model::Type::CanonicalUser;
    if (type == "Group")
        return Aws::S3::Model::Type::Group;
    return Aws::S3::Model::Type::NOT_SET;
}
```

请参阅 [Github](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/cpp/example_code/s3/get_put_bucket_acl.cpp) 上的完整示例。

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

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

## 先决条件
<a name="codeExamplePrereq"></a>

在开始之前，建议您先阅读[开始使用 适用于 C\$1\$1 的 AWS SDK](getting-started.md)。

下载示例代码并按[代码示例入门](getting-started-code-examples.md)中所述构建解决方案。

要运行这些示例，您的代码用于发出请求的用户配置文件必须具有适当的权限 AWS （适用于服务和操作）。有关更多信息，请参阅[提供 AWS 凭证](credentials.md)。

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

您可以为特定 S3 存储桶设置存储桶策略，方法`S3Client`是调用`PutBucketPolicy`函数并在中为其提供存储桶名称和策略的 JSON 表示形式[PutBucketPolicyRequest](https://docs.aws.amazon.com/sdk-for-cpp/latest/api/aws-cpp-sdk-s3/html/class_aws_1_1_s3_1_1_model_1_1_put_bucket_policy_request.html)。

 **代码** 

```
//! Build a policy JSON string.
/*!
  \param userArn: Aws user Amazon Resource Name (ARN).
      For more information, see https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html#identifiers-arns.
  \param bucketName: Name of a bucket.
  \return String: Policy as JSON string.
*/

Aws::String getPolicyString(const Aws::String &userArn,
                            const Aws::String &bucketName) {
    return
            "{\n"
            "   \"Version\":\"2012-10-17\",\n"
            "   \"Statement\":[\n"
            "       {\n"
            "           \"Sid\": \"1\",\n"
            "           \"Effect\": \"Allow\",\n"
            "           \"Principal\": {\n"
            "               \"AWS\": \""
            + userArn +
            "\"\n""           },\n"
            "           \"Action\": [ \"s3:getObject\" ],\n"
            "           \"Resource\": [ \"arn:aws:s3:::"
            + bucketName +
            "/*\" ]\n"
            "       }\n"
            "   ]\n"
            "}";
}
```

```
bool AwsDoc::S3::putBucketPolicy(const Aws::String &bucketName,
                                 const Aws::String &policyBody,
                                 const Aws::S3::S3ClientConfiguration &clientConfig) {
    Aws::S3::S3Client s3Client(clientConfig);

    std::shared_ptr<Aws::StringStream> request_body =
            Aws::MakeShared<Aws::StringStream>("");
    *request_body << policyBody;

    Aws::S3::Model::PutBucketPolicyRequest request;
    request.SetBucket(bucketName);
    request.SetBody(request_body);

    Aws::S3::Model::PutBucketPolicyOutcome outcome =
            s3Client.PutBucketPolicy(request);

    if (!outcome.IsSuccess()) {
        std::cerr << "Error: putBucketPolicy: "
                  << outcome.GetError().GetMessage() << std::endl;
    } else {
        std::cout << "Set the following policy body for the bucket '" <<
                  bucketName << "':" << std::endl << std::endl;
        std::cout << policyBody << std::endl;
    }

    return outcome.IsSuccess();
}
```

**注意**  
[Aws:: Utils:: Json:: JsonValue](https://docs.aws.amazon.com/sdk-for-cpp/latest/api/aws-cpp-sdk-core/html/class_aws_1_1_utils_1_1_json_1_1_json_value.html) 实用程序类可以用来帮助你构造要传递给的有效 JSON 对象。`PutBucketPolicy`

请参阅 [Github](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/cpp/example_code/s3/put_bucket_policy.cpp) 上的完整示例。

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

要检索 Amazon S3 存储桶的策略，请调用 `S3Client`'s `GetBucketPolicy` 函数，将存储桶的名称传递给它[GetBucketPolicyRequest](https://docs.aws.amazon.com/sdk-for-cpp/latest/api/aws-cpp-sdk-s3/html/class_aws_1_1_s3_1_1_model_1_1_get_bucket_policy_request.html)。

 **代码** 

```
bool AwsDoc::S3::getBucketPolicy(const Aws::String &bucketName,
                                 const Aws::S3::S3ClientConfiguration &clientConfig) {
    Aws::S3::S3Client s3Client(clientConfig);

    Aws::S3::Model::GetBucketPolicyRequest request;
    request.SetBucket(bucketName);

    Aws::S3::Model::GetBucketPolicyOutcome outcome =
            s3Client.GetBucketPolicy(request);

    if (!outcome.IsSuccess()) {
        const Aws::S3::S3Error &err = outcome.GetError();
        std::cerr << "Error: getBucketPolicy: "
                  << err.GetExceptionName() << ": " << err.GetMessage() << std::endl;
    } else {
        Aws::StringStream policy_stream;
        Aws::String line;

        outcome.GetResult().GetPolicy() >> line;
        policy_stream << line;

        std::cout << "Retrieve the policy for bucket '" << bucketName << "':\n\n" <<
                  policy_stream.str() << std::endl;
    }

    return outcome.IsSuccess();
}
```

请参阅 [Github](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/cpp/example_code/s3/get_bucket_policy.cpp) 上的完整示例。

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

要删除存储桶策略，请调用 `S3Client`'s `DeleteBucketPolicy` 函数，并在中为其提供存储桶名称[DeleteBucketPolicyRequest](https://docs.aws.amazon.com/sdk-for-cpp/latest/api/aws-cpp-sdk-s3/html/class_aws_1_1_s3_1_1_model_1_1_delete_bucket_policy_request.html)。

 **代码** 

```
bool AwsDoc::S3::deleteBucketPolicy(const Aws::String &bucketName,
                                    const Aws::S3::S3ClientConfiguration &clientConfig) {
    Aws::S3::S3Client client(clientConfig);

    Aws::S3::Model::DeleteBucketPolicyRequest request;
    request.SetBucket(bucketName);

    Aws::S3::Model::DeleteBucketPolicyOutcome outcome = client.DeleteBucketPolicy(request);

    if (!outcome.IsSuccess()) {
        const Aws::S3::S3Error &err = outcome.GetError();
        std::cerr << "Error: deleteBucketPolicy: " <<
                  err.GetExceptionName() << ": " << err.GetMessage() << std::endl;
    } else {
        std::cout << "Policy was deleted from the bucket." << std::endl;
    }

    return outcome.IsSuccess();
}
```

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

请参阅 [Github](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/cpp/example_code/s3/delete_bucket_policy.cpp) 上的完整示例。

## 更多信息
<a name="more-info"></a>
+  [PutBucketPolicy](https://docs.aws.amazon.com/AmazonS3/latest/API/PutBucketPolicy.html)在 Amazon 简单存储服务 API 参考中
+  [GetBucketPolicy](https://docs.aws.amazon.com/AmazonS3/latest/API/GetBucketPolicy.html)在 Amazon 简单存储服务 API 参考中
+  [DeleteBucketPolicy](https://docs.aws.amazon.com/AmazonS3/latest/API/DeleteBucketPolicy.html)在 Amazon 简单存储服务 API 参考中
+  《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)

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

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

## 先决条件
<a name="codeExamplePrereq"></a>

在开始之前，建议您先阅读[开始使用 适用于 C\$1\$1 的 AWS SDK](getting-started.md)。

下载示例代码并按[代码示例入门](getting-started-code-examples.md)中所述构建解决方案。

要运行这些示例，您的代码用于发出请求的用户配置文件必须具有适当的权限 AWS （适用于服务和操作）。有关更多信息，请参阅[提供 AWS 凭证](credentials.md)。

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

要设置 Amazon S3 存储桶的网站配置，请使用[PutBucketWebsiteRequest](https://docs.aws.amazon.com/sdk-for-cpp/latest/api/aws-cpp-sdk-s3/html/class_aws_1_1_s3_1_1_model_1_1_put_bucket_website_request.html)对象中提供的包含存储桶名称及其网站配置的[WebsiteConfiguration](https://docs.aws.amazon.com/sdk-for-cpp/latest/api/aws-cpp-sdk-s3/html/class_aws_1_1_s3_1_1_model_1_1_website_configuration.html)对象调用 `S3Client`'s `PutBucketWebsite` 函数。

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

 **代码** 

```
bool AwsDoc::S3::putWebsiteConfig(const Aws::String &bucketName,
                                  const Aws::String &indexPage, const Aws::String &errorPage,
                                  const Aws::S3::S3ClientConfiguration &clientConfig) {
    Aws::S3::S3Client client(clientConfig);

    Aws::S3::Model::IndexDocument indexDocument;
    indexDocument.SetSuffix(indexPage);

    Aws::S3::Model::ErrorDocument errorDocument;
    errorDocument.SetKey(errorPage);

    Aws::S3::Model::WebsiteConfiguration websiteConfiguration;
    websiteConfiguration.SetIndexDocument(indexDocument);
    websiteConfiguration.SetErrorDocument(errorDocument);

    Aws::S3::Model::PutBucketWebsiteRequest request;
    request.SetBucket(bucketName);
    request.SetWebsiteConfiguration(websiteConfiguration);

    Aws::S3::Model::PutBucketWebsiteOutcome outcome =
            client.PutBucketWebsite(request);

    if (!outcome.IsSuccess()) {
        std::cerr << "Error: PutBucketWebsite: "
                  << outcome.GetError().GetMessage() << std::endl;
    } else {
        std::cout << "Success: Set website configuration for bucket '"
                  << bucketName << "'." << std::endl;
    }

    return outcome.IsSuccess();
}
```

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

请参阅 [Github](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/cpp/example_code/s3/put_website_config.cpp) 上的完整示例。

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

要获取 Amazon S3 存储桶`S3Client`的网站配置，请调用[GetBucketWebsiteRequest](https://docs.aws.amazon.com/sdk-for-cpp/latest/api/aws-cpp-sdk-s3/html/class_aws_1_1_s3_1_1_model_1_1_get_bucket_website_request.html)包含要检索配置的存储桶名称的's `GetBucketWebsite` 函数。

配置将作为结果[GetBucketWebsiteResult](https://docs.aws.amazon.com/sdk-for-cpp/latest/api/aws-cpp-sdk-s3/html/class_aws_1_1_s3_1_1_model_1_1_get_bucket_website_result.html)对象中的对象返回。如果该存储桶没有网站配置，则会返回 `null`。

 **代码** 

```
bool AwsDoc::S3::getWebsiteConfig(const Aws::String &bucketName,
                                  const Aws::S3::S3ClientConfiguration &clientConfig) {
    Aws::S3::S3Client s3Client(clientConfig);

    Aws::S3::Model::GetBucketWebsiteRequest request;
    request.SetBucket(bucketName);

    Aws::S3::Model::GetBucketWebsiteOutcome outcome =
            s3Client.GetBucketWebsite(request);

    if (!outcome.IsSuccess()) {
        const Aws::S3::S3Error &err = outcome.GetError();

        std::cerr << "Error: GetBucketWebsite: "
                  << err.GetMessage() << std::endl;
    } else {
        Aws::S3::Model::GetBucketWebsiteResult websiteResult = outcome.GetResult();

        std::cout << "Success: GetBucketWebsite: "
                  << std::endl << std::endl
                  << "For bucket '" << bucketName << "':"
                  << std::endl
                  << "Index page : "
                  << websiteResult.GetIndexDocument().GetSuffix()
                  << std::endl
                  << "Error page: "
                  << websiteResult.GetErrorDocument().GetKey()
                  << std::endl;
    }

    return outcome.IsSuccess();
}
```

请参阅 [Github](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/cpp/example_code/s3/get_website_config.cpp) 上的完整示例。

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

要删除 Amazon S3 存储桶的网站配置，请使用[DeleteBucketWebsiteRequest](https://docs.aws.amazon.com/sdk-for-cpp/latest/api/aws-cpp-sdk-s3/html/class_aws_1_1_s3_1_1_model_1_1_delete_bucket_website_request.html):调用包含要从中删除配置的存储桶名称的 `S3Client`'s `DeleteBucketWebsite` 函数。

 **代码** 

```
bool AwsDoc::S3::deleteBucketWebsite(const Aws::String &bucketName,
                                     const Aws::S3::S3ClientConfiguration &clientConfig) {
    Aws::S3::S3Client client(clientConfig);
    Aws::S3::Model::DeleteBucketWebsiteRequest request;
    request.SetBucket(bucketName);

    Aws::S3::Model::DeleteBucketWebsiteOutcome outcome =
            client.DeleteBucketWebsite(request);

    if (!outcome.IsSuccess()) {
        auto err = outcome.GetError();
        std::cerr << "Error: deleteBucketWebsite: " <<
                  err.GetExceptionName() << ": " << err.GetMessage() << std::endl;
    } else {
        std::cout << "Website configuration was removed." << std::endl;
    }

    return outcome.IsSuccess();
}
```

请参阅 [Github](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/cpp/example_code/s3/delete_website_config.cpp) 上的完整示例。

## 更多信息
<a name="more-information"></a>
+  《Amazon Simple Storage Service API 参考》中的 [PutBucketWebsite](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketPUTwebsite.html)
+  《Amazon Simple Storage Service API 参考》中的 [GetBucketWebsite](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketGETwebsite.html)
+  《Amazon Simple Storage Service API 参考》中的 [DeleteBucketWebsite](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketDELETEwebsite.html)

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

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

**注意**  
为避免因上传不完整或部分上传而产生费用，我们建议您在 Amazon S3 存储桶上启用[AbortIncompleteMultipartUpload](https://docs.aws.amazon.com/AmazonS3/latest/userguide/mpu-abort-incomplete-mpu-lifecycle-config.html)生命周期规则。  
该规则指示 Amazon S3 中止在启动后没有在指定天数内完成的分段上传。当超过设置的时间限制时，Amazon S3 将中止上传，然后删除未完成的上传数据。  
有关更多信息，请参阅《Amazon S3 用户指南》中的[在存储桶上设置生命周期配置](https://docs.aws.amazon.com/AmazonS3/latest/userguide/how-to-set-lifecycle-configuration-intro.html)。

## 先决条件
<a name="codeExamplePrereq"></a>

在开始之前，建议您先阅读[开始使用 适用于 C\$1\$1 的 AWS SDK](getting-started.md)。

下载示例代码并按[代码示例入门](getting-started-code-examples.md)中所述构建解决方案。

要运行这些示例，您的代码用于发出请求的用户配置文件必须具有适当的权限 AWS （适用于服务和操作）。有关更多信息，请参阅[提供 AWS 凭证](credentials.md)。

## 使用 `TransferManager` 上传和下载对象
<a name="stream"></a>

此示例演示了 [https://docs.aws.amazon.com/sdk-for-cpp/latest/api/aws-cpp-sdk-transfer/html/class_aws_1_1_transfer_1_1_transfer_manager.html](https://docs.aws.amazon.com/sdk-for-cpp/latest/api/aws-cpp-sdk-transfer/html/class_aws_1_1_transfer_1_1_transfer_manager.html) 如何在内存中传输大型对象。`UploadFile` 和 `DownloadFile` 方法都是异步调用的，并返回一个 `TransferHandle` 来管理请求的状态。如果上传的对象大于 `bufferSize`，则将执行分段上传。`bufferSize` 默认为 5 MB，但可以通过进行 [https://docs.aws.amazon.com/sdk-for-cpp/latest/api/aws-cpp-sdk-transfer/html/struct_aws_1_1_transfer_1_1_transfer_manager_configuration.html](https://docs.aws.amazon.com/sdk-for-cpp/latest/api/aws-cpp-sdk-transfer/html/struct_aws_1_1_transfer_1_1_transfer_manager_configuration.html) 配置。

```
        auto s3_client = Aws::MakeShared<Aws::S3::S3Client>("S3Client");
        auto executor = Aws::MakeShared<Aws::Utils::Threading::PooledThreadExecutor>("executor", 25);
        Aws::Transfer::TransferManagerConfiguration transfer_config(executor.get());
        transfer_config.s3Client = s3_client;

        // Create buffer to hold data received by the data stream.
        Aws::Utils::Array<unsigned char> buffer(BUFFER_SIZE);

        // The local variable 'streamBuffer' is captured by reference in a lambda.
        // It must persist until all downloading by the 'transfer_manager' is complete.
        Stream::PreallocatedStreamBuf streamBuffer(buffer.GetUnderlyingData(), buffer.GetLength());

        auto transfer_manager = Aws::Transfer::TransferManager::Create(transfer_config);

        auto uploadHandle = transfer_manager->UploadFile(LOCAL_FILE, BUCKET, KEY, "text/plain", Aws::Map<Aws::String, Aws::String>());
        uploadHandle->WaitUntilFinished();
        bool success = uploadHandle->GetStatus() == Transfer::TransferStatus::COMPLETED; 
      
        if (!success)
        {
            auto err = uploadHandle->GetLastError();           
            std::cout << "File upload failed:  "<< err.GetMessage() << std::endl;
        }
        else
        {
            std::cout << "File upload finished." << std::endl;

            auto downloadHandle = transfer_manager->DownloadFile(BUCKET,
                KEY,
                [&]() { //Define a lambda expression for the callback method parameter to stream back the data.
                    return Aws::New<MyUnderlyingStream>("TestTag", &streamBuffer);
                });
            downloadHandle->WaitUntilFinished();// Block calling thread until download is complete.
            auto downStat = downloadHandle->GetStatus();
            if (downStat != Transfer::TransferStatus::COMPLETED)
            {
                auto err = downloadHandle->GetLastError();
                std::cout << "File download failed:  " << err.GetMessage() << std::endl;
            }
            std::cout << "File download to memory finished."  << std::endl;
```

请参阅 [Github](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/cpp/example_code/transfer-manager/transferOnStream.cpp) 上的完整示例。

# 使用 `S3CrtClient` 执行 Amazon S3 操作
<a name="examples-s3-crt"></a>

该`S3CrtClient`课程在 1.9 版中可用， 适用于 C\$1\$1 的 AWS SDK 它提高了向 Amazon S3 上传和下载大型数据文件的吞吐量。有关此版本改进的更多信息，请参阅[使用 适用于 C\$1\$1 的 AWS SDK v1.9 提高 Amazon S3 吞吐量](https://github.com/aws/aws-sdk-cpp/wiki/Improving-S3-Throughput-with-AWS-SDK-for-CPP-v1.9)

`S3CrtClient` 构建于 [AWS 通用运行时（CRT）库](https://docs.aws.amazon.com/sdkref/latest/guide/common-runtime.html)之上。

**注意**  
为避免因上传不完整或部分上传而产生费用，我们建议您在 Amazon S3 存储桶上启用[AbortIncompleteMultipartUpload](https://docs.aws.amazon.com/AmazonS3/latest/userguide/mpu-abort-incomplete-mpu-lifecycle-config.html)生命周期规则。  
该规则指示 Amazon S3 中止在启动后没有在指定天数内完成的分段上传。当超过设置的时间限制时，Amazon S3 将中止上传，然后删除未完成的上传数据。  
有关更多信息，请参阅《Amazon S3 用户指南》中的[在存储桶上设置生命周期配置](https://docs.aws.amazon.com/AmazonS3/latest/userguide/how-to-set-lifecycle-configuration-intro.html)。

## 先决条件
<a name="codeExamplePrereq"></a>

在开始之前，建议您先阅读[开始使用 适用于 C\$1\$1 的 AWS SDK](getting-started.md)。

下载示例代码并按[代码示例入门](getting-started-code-examples.md)中所述构建解决方案。

要运行这些示例，您的代码用于发出请求的用户配置文件必须具有适当的权限 AWS （适用于服务和操作）。有关更多信息，请参阅[提供 AWS 凭证](credentials.md)。

## 使用 `S3CrtClient` 上传和下载对象
<a name="stream"></a>

此示例演示如何使用 [https://docs.aws.amazon.com/sdk-for-cpp/latest/api/aws-cpp-sdk-s3-crt/html/class_aws_1_1_s3_crt_1_1_s3_crt_client.html](https://docs.aws.amazon.com/sdk-for-cpp/latest/api/aws-cpp-sdk-s3-crt/html/class_aws_1_1_s3_crt_1_1_s3_crt_client.html)。该示例创建一个存储桶，上传一个对象，下载该对象，然后删除该文件和存储桶。PUT 操作会转化为分段上传。GET 操作会转化为多个“分范围”GET 请求。有关分段上传的更多信息，请参阅《Amazon S3 用户指南》中的[使用分段上传来上传和复制对象](https://docs.aws.amazon.com/AmazonS3/latest/userguide/mpuoverview.html)。

在此示例中，提供的数据文件 `ny.json` 以分段上传的形式上传。这一点可以在程序成功运行后，通过查看调试日志来确认。

如果上传失败，底层 CRT 库中会发出 `AbortMultipartUpload`，以清理所有已上传的部分。但是，并非所有错误/故障都可以在内部处理（例如拔掉网线）。建议您在 Amazon S3 存储桶上创建生命周期规则，以确保部分上传的数据不会滞留在您的账户中（部分上传的数据仍然会产生费用）。有关如何设置生命周期规则，请参阅[发现并删除未完成的分段上传以降低 Amazon S3 费用](https://aws.amazon.com/blogs/aws-cost-management/discovering-and-deleting-incomplete-multipart-uploads-to-lower-amazon-s3-costs/ )。

**使用调试日志浏览分段上传的详细信息**

1. 在 `main()` 函数中，注意带有“TODO”注释的代码，这些注释提供了更新代码的说明。

   1. 对于 `file_name`：从代码注释中提供的链接下载示例数据文件 `ny.json`，或使用您自己的大型数据文件。

   1. 对于`region`：使用枚举将`region`变量更新为账户 AWS 区域 的变量。要找到您的账户所在区域，请登录到 AWS 管理控制台，然后在右上角找到该区域。

1. 编译示例。

1. 将变量 `file_name` 指定的文件复制到您的可执行文件夹，然后运行 `s3-crt-demo` 可执行文件。

1. 在您的可执行文件夹中，找到最新的 `.log` 文件。

1. 打开日志文件，选择**搜索**，然后输入 **partNumber**。

1. 该日志包含类似以下内容的条目，其中为上传文件的每个部分指定了 `partNumber` 和 `uploadId`：

    `PUT /my-object partNumber=1&uploadId=gsk8vDbmnlA5EseDo._LDEgq22Qmt0SeuszYxMsZ9ABt503VqDIFOP8xzZI1P0zp.ToS.qo5kK16HNWogZF3KpRo.Dc7QnLZIK0BTmzCWwWoPax4T21hvP6nPdz9591F content-length:8388608 host:my-bucketasdfasdf.s3.us-east-2.amazonaws.com x-amz-content-sha256:UNSIGNED-PAYLOAD`

    and 

    `PUT /my-object partNumber=2&uploadId=gsk8vDbmnlA5EseDo._LDEgq22Qmt0SeuszYxMsZ9ABt503VqDIFOP8xzZI1P0zp.ToS.qo5kK16HNWogZF3KpRo.Dc7QnLZIK0BTmzCWwWoPax4T21hvP6nPdz9591F content-length:8388608 host:my-bucketasdfasdf.s3.us-east-2.amazonaws.com x-amz-content-sha256:UNSIGNED-PAYLOAD `

请参阅 [Github](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/cpp/example_code/s3-crt/s3-crt-demo.cpp) 上的完整示例。