

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

在您将文件上传至 Amazon S3 时，文件会存储为 S3 *对象*。对象由文件数据和描述对象的元数据组成。一个存储桶中可以有无限量的对象。您需要拥有存储桶写入权限，才能将文件上传至 Amazon S3 存储桶。有关访问权限的更多信息，请参阅[Amazon S3 的身份和访问管理](security-iam.md)。

您可以将任何类型的文件上传至 S3 存储桶，包括图像、备份、数据、电影等。可使用 Amazon S3 控制台上传的文件的最大大小为 160 GB。要上传大于 160GB 的文件，请使用 AWS Command Line Interface（AWS CLI）、AWS SDK 或 Amazon S3 REST API。

如果启用了版本控制的存储桶中已存在所上传对象的键名，则 Amazon S3 会创建该对象的另一个版本，而不是替换现有对象。有关启用版本控制的更多信息，请参阅[在存储桶上启用版本控制](manage-versioning-examples.md)。

 根据您要上传的数据大小，Amazon S3 提供以下选项：
+ **使用 AWS SDK、REST API 或 AWS CLI 在单个操作中上传对象** – 您可以在单个 `PUT` 操作中上传最大为 5GB 的单个对象。
+ **使用 Amazon S3 控制台上传单个对象**** –** 通过 Amazon S3 控制台，您可以上传最大 160GB 的单个对象。
+ **使用 AWS SDK、REST API 或 AWS CLI 分段上传对象**** – **您可以使用分段上传 API 操作来上传单个大型对象（最大大小为 50TB）。

  分段上传 API 操作旨在改进大型对象的上传体验。您可以分段上传对象。这些对象分段可以按任何顺序并行独立上传。您可以对大小在 5 MB 到 50 TB 范围内的对象使用分段上传。有关更多信息，请参阅 [在 Amazon S3 中使用分段上传来上传和复制对象](mpuoverview.md)。

要上传大于 5 TB 的文件，请使用 Java v1/v2、Python 或 AWS CLI SDK 版本的 S3 Transfer Manager。要获得最佳性能，请将最新的 AWS 通用运行时（CRT）与这些 SDK 配合使用，该运行时已经过优化，可以提高资源利用率。

从内存流上传大型对象时，CRT 会缓冲每个分段，最多占用 5 GB 内存，从而按照分配的内存来限制总吞吐量。您可以使用配置选项（例如，对于 Java SDK 使用 `maxNativeMemoryLimitInBytes`）来调整 CRT 内存限制。对于从磁盘上传，CRT 会自动切换到直接磁盘流式传输而不是中间分段缓冲，从而提高内存使用率。系统会自动为大型对象启用此行为，不过您也可通过请求参数（例如，对于 AWS CLI 使用 `should_stream`，对于 Java SDK 使用 `CRT_MEMORY_BUFFER_DISABLED`）为较小的文件启用此行为。

当您上传对象时，默认情况下，将使用具有 Amazon S3 托管式密钥的服务器端加密（SSE-S3）自动加密对象。当您下载对象时，该对象将被解密。有关更多信息，请参阅[为 Amazon S3 存储桶设置默认服务器端加密行为](bucket-encryption.md)和[利用加密来保护数据](UsingEncryption.md)。

上传对象时，如果您想使用不同类型的默认加密，也可以在 S3 `PUT` 请求中指定具有 AWS Key Management Service（AWS KMS）密钥的服务器端加密（SSE-KMS），或者将目标存储桶中的默认加密配置设置为使用 SSE-KMS 来加密数据。有关 SSE-KMS 的更多信息，请参阅 [使用 AWS KMS (SSE-KMS) 指定服务器端加密](specifying-kms-encryption.md)。如果您希望使用其他账户拥有的 KMS 密钥，则您必须有权使用该密钥。有关 KMS 密钥的跨账户权限的更多信息，请参阅《AWS Key Management Service 开发人员指南》**中的[创建其他账户可以使用的 KMS 密钥](https://docs.aws.amazon.com//kms/latest/developerguide/key-policy-modifying-external-accounts.html#cross-account-console)。

如果您在 Amazon S3 中遇到拒绝访问（403 禁止访问）错误，请参阅[排查 Amazon S3 中的拒绝访问（403 Forbidden）错误](troubleshoot-403-errors.md)详细了解其常见原因。

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

### 使用 S3 控制台
<a name="upload-objects-by-drag-and-drop"></a>

此过程介绍如何使用控制台将对象和文件夹上传到 Amazon S3 存储桶。

上传对象时，对象键名称是文件名和任何可选前缀。在 Amazon S3 控制台中，您可以创建文件夹来组织对象。在 Amazon S3 中，文件夹表示为出现在对象键名称中的前缀。如果您将单个对象上传到 Amazon S3 控制台中的文件夹，则文件夹名称将包含在对象键名称中。

例如，如果您将名为的对象上传 `sample1.jpg` 到名为 `backup` 的文件夹，则密钥名称为 `backup/sample1.jpg`。但是，对象会像 `sample1.jpg` 在 `backup` 文件夹中一样在控制台中显示。有关键名称的更多信息，请参阅 [使用对象元数据](UsingMetadata.md)。

**注意**  
如果在 Amazon S3 控制台中重命名对象或更改诸如**存储类**、**加密**或**元数据**等任何属性，将创建一个新对象来替换旧对象。如果启用 S3 版本控制，则会创建对象的新版本，而现有对象将变为旧版本。更改属性的角色也会成为新对象（或对象版本）的拥有者。

上传文件夹时，Amazon S3 会将所有文件和子文件夹从指定文件夹中上传至存储桶。然后，它会分配由上传文件名和文件夹名组成的对象键名。例如，如果您上传包含 `/images` 和 `sample1.jpg` 这两个文件的名为 `sample2.jpg` 的文件夹，则 Amazon S3 会上传这两个文件，然后分配相应的键名 `images/sample1.jpg` 和 `images/sample2.jpg`。键名包括作为前缀的文件夹名。Amazon S3 控制台仅显示最后一个“`/`”后面的键名部分。例如，在 `images` 文件夹中，`images/sample1.jpg` 和 `images/sample2.jpg` 对象显示为 `sample1.jpg` 和 `sample2.jpg`。<a name="upload-files-folders"></a>

**将文件夹和文件上传到 S3 存储桶**

1. 登录到 AWS 管理控制台，然后通过以下网址打开 Amazon S3 控制台：[https://console.aws.amazon.com/s3/](https://console.aws.amazon.com/s3/)。

1. 在左侧导航窗格中，选择**存储桶**。

1. 在 **Buckets**（存储桶） 列表中，请选择要将文件夹和文件上传到的存储桶的名称。

1. 请选择 **Upload**（上传）。

1. 在**上传**窗口中，执行下列操作之一：
   + 将文件和文件夹拖放到**上传**窗口。
   + 选择**添加文件**或**添加文件夹**，选择要上传的文件或文件夹，然后选择**打开**。

1. 要启用版本控制，请在**目标**下选择**启用存储桶版本控制**。

1. 要上传列出的文件和文件夹而不配置其他上传选项，请选择页面底部的**上传**。

   Amazon S3 会上传您的对象和文件夹。上传完成后，您可以在**上传：状态**页面上看到成功消息。<a name="configure-additional-properties"></a>

**配置其他对象属性**

1. 要更改访问控制列表权限，请选择 **Permissions**（权限）。

1. 在 **Access control list (ACL)** [访问控制列表 (ACL)]下，编辑权限。

   有关对象访问权限的信息，请参阅 [使用 S3 控制台为对象设置 ACL 权限](managing-acls.md#set-object-permissions)。您可以向公众（世界上的每一个人）授予对您的对象的读取访问权限，使其能够获取您正在上传的所有文件。但是，我们建议您不要更改公共读取访问的默认设置。授予公有读取访问权限适用于一小部分的使用案例（如存储桶用于网站时）。您始终可以在上传对象后更改对象权限。

1. 要配置其他附加属性，请选择 **Properties**（属性）。

1. 在**存储类**下，为正在上传的文件选择存储类。

   有关存储类的更多信息，请参阅 [了解和管理 Amazon S3 存储类](storage-class-intro.md)。

1. 要更新对象的加密设置，请在**服务器端加密设置**下执行以下操作：

   1. 选择 **Specify an encryption key**（指定加密密钥）。

   1. 在**加密设置**下，选择**使用默认加密的存储桶设置**或**覆盖默认加密的存储桶设置**。

   1. 如果您选择**覆盖默认加密的存储桶设置**，则必须配置以下加密设置。
      + 要使用由 Amazon S3 托管的密钥加密上传的文件，请选择 **Amazon S3 托管式密钥（SSE-S3）**。

        有关更多信息，请参阅 [使用具有 Amazon S3 托管式密钥的服务器端加密（SSE-S3）](UsingServerSideEncryption.md)。
      + 要使用存储在 AWS Key Management Service（AWS KMS）中的密钥加密上传的文件，请选择 **AWS Key Management Service 密钥（SSE-KMS）**。然后，为 **AWS KMS 密钥**选择以下选项之一：
        + 要从可用的 KMS 密钥列表中进行选择，请选择**从您的 AWS KMS keys 中进行选择**，然后从可用密钥的列表中选择您的 **KMS 密钥**。

          AWS 托管式密钥（`aws/s3`）和您的客户自主管理型密钥都显示在此列表中。有关客户自主管理型密钥的更多信息，请参阅《AWS Key Management Service 开发人员指南》**中的[客户密钥和 AWS 密钥](https://docs.aws.amazon.com//kms/latest/developerguide/concepts.html#key-mgmt)。
        + 要输入 KMS 密钥 ARN，请选择**输入 AWS KMS key ARN**，然后在显示的字段中输入您的 KMS 密钥 ARN。
        + 要在 AWS KMS 控制台中创建新的客户自主管理型密钥，请选择**创建 KMS 密钥**。

          有关创建 AWS KMS key 的更多信息，请参阅《AWS Key Management Service 开发人员指南》**中的[创建密钥](https://docs.aws.amazon.com//kms/latest/developerguide/create-keys.html)。
**重要**  
您只能使用与存储桶所在相同的 AWS 区域中可用的 KMS 密钥。Amazon S3 控制台仅列出与存储桶位于同一区域中的前 100 个 KMS 密钥。要使用未列出的 KMS 密钥，您必须输入 KMS 密钥 ARN。如果您希望使用其他账户拥有的 KMS 密钥，则必须首先有权使用该密钥，然后必须输入相应的 KMS 密钥 ARN。  
Amazon S3 仅支持对称加密 KMS 密钥，不支持非对称 KMS 密钥。有关更多信息，请参阅《AWS Key Management Service 开发人员指南》**中的[确定对称和非对称 KMS 密钥](https://docs.aws.amazon.com//kms/latest/developerguide/find-symm-asymm.html)。

1. 要使用其他校验和，请选择 **On**（打开）。然后对于 **Checksum function**（校验和函数），选择要使用的函数。Amazon S3 在收到整个对象后计算并存储校验和值。您可以使用 **Precalculated value**（预计算值）框来提供预先计算的值。这样，Amazon S3 会将您提供的值与其计算的值进行比较。如果两个值不匹配，Amazon S3 将生成错误。

   其他校验和使您能够指定要用于验证数据的校验和算法。有关其他校验和的更多信息，请参阅[在 Amazon S3 中检查对象完整性](checking-object-integrity.md)。

1. 要向上传的所有对象添加标签，请选择 **Add tag (添加标签)**。在**键**字段中输入标签名称。输入标签的值。

   对象标签为您提供了对存储进行分类的方法。每个标签都是一个键-值对。键和标签值区分大小写。对于每个对象，您最多可以有 10 个标签。标签键的长度最大可以为 128 个 Unicode 字符，标签值的长度最大可以为 255 个 Unicode 字符。有关对象标签的更多信息，请参阅 [使用标签对对象进行分类](object-tagging.md)。

1. 要添加元数据，请选择**添加元数据**。

   1. 在**类型**下，请选择**系统定义**或**用户定义**。

      对于系统定义元数据，您可以选择通用的 HTTP 标头，如 **Content-Type** 和 **Content-Disposition**。有关系统定义元数据的列表以及您能否添加值的信息，请参阅[系统定义的对象元数据](UsingMetadata.md#SysMetadata)。以前缀 `x-amz-meta-` 开头的任何元数据都被视为用户定义的元数据。用户定义元数据会与对象存储在一起，并会在您下载该对象时返回。密钥及其值均必须符合 US-ASCII 标准。用户定义元数据最大可为 2 KB。如需详细了解系统定义和用户定义的元数据，请参阅[使用对象元数据](UsingMetadata.md)。

   1. 对于**键**，请选择一个键。

   1. 键入该键的值。

1. 要上传对象，请选择**上传**。

   Amazon S3 将上传您的对象。上传完成后，您可以在**上传：状态**页面上看到成功消息。

1. 请选择 **Exit**（退出）。

### 使用 AWS CLI
<a name="UploadObjSingleOpCLI"></a>

您可以发送 `PUT` 请求，在单个操作中上传最大 5 GB 的对象。有关更多信息，请参阅 *AWS CLI 命令参考*中的 [https://docs.aws.amazon.com/cli/latest/reference/s3api/put-object.html#examples](https://docs.aws.amazon.com/cli/latest/reference/s3api/put-object.html#examples) 示例。

### 使用 REST API
<a name="UploadObjSingleOpREST"></a>

您可以发送 REST 请求以上传对象。您可以发送 `PUT` 请求以在单个操作中上传数据。有关更多信息，请参阅 [PUT Object](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPUT.html)。

### 使用 AWS SDK
<a name="UploadInSingleOp"></a>

有关如何使用 AWS SDK 上传对象的示例，请参阅《Amazon Simple Storage Service API 参考》**中的[代码示例](https://docs.aws.amazon.com/AmazonS3/latest/API/s3_example_s3_PutObject_section.html)。

有关使用不同 AWS SDK 的一般信息，请参阅《Amazon Simple Storage Service API 参考》**中的[使用 AWS SDK 通过 Amazon S3 进行开发](https://docs.aws.amazon.com/AmazonS3/latest/API/sdk-general-information-section.html)。

## 防止上传具有相同键名称的对象
<a name="upload-objects-with-same-key-name"></a>

在对上传操作使用有条件写入来创建对象之前，您可以检查存储桶中是否存在该对象。这样可以防止覆盖现有数据。当上传时，有条件写入将验证存储桶中尚不存在具有相同键名称的现有对象。

可以将有条件写入用于 [https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html) 或 [CompleteMultipartUpload](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html) 请求。

有关有条件请求的更多信息，请参阅[使用有条件请求向 S3 操作添加前提条件](conditional-requests.md)。

# 在 Amazon S3 中使用分段上传来上传和复制对象
<a name="mpuoverview"></a>

分段上传支持您将单个对象作为一组分段上传到 Amazon S3。每个分段都是对象数据的连续部分。您可以独立上传以及按任意顺序上传这些对象分段。对于上传，更新后的 AWS 客户端会自动计算对象的校验和，并将其连同对象的大小一起作为请求的一部分发送到 Amazon S3。如果任意分段传输失败，可以重新传输该分段且不会影响其它分段。上传完对象的所有分段后，Amazon S3 将汇集这些分段并创建对象。最佳做法是对 100 MB 或更大的对象使用分段上传，而不是在单个操作中上传它们。

使用分段上传可提供以下优势：
+ **提高吞吐量** – 您可以并行上传分段以提高吞吐量。
+ **从任何网络问题中快速恢复** – 较小的分段大小可以将由于网络错误而需重启失败的上传所产生的影响降至最低。
+ **暂停和恢复对象上传** – 您可以在一段时间内逐步上传对象分段。启动分段上传后，不存在过期期限；您必须显式地完成或停止分段上传。
+ **在您知道对象的最终大小前开始上传**：您可以在创建对象时将其上传。

我们建议您按以下方式使用分段上传：
+ 如果您在稳定的高带宽网络上传大型对象，请通过并行上传对象分段来实现多线程性能，从而使用分段上传以最大限度地利用您的可用带宽。
+ 如果您通过断点网络进行上传，请使用分段上传，通过避免重新开始上传来提高应对网络错误的复原能力。在使用分段上传时，只需重试上传在上传期间中断的分段即可。而无需从头重新开始上传对象。

**注意**  
有关将 Amazon S3 Express One Zone 存储类与目录存储桶配合使用的更多信息，请参阅 [S3 Express One Zone](directory-bucket-high-performance.md#s3-express-one-zone) 和[使用目录存储桶](directory-buckets-overview.md)。有关将分段上传用于 S3 Express One Zone 和目录存储桶的更多信息，请参阅[对目录桶使用分段上传](s3-express-using-multipart-upload.md)。

## 分段上传流程
<a name="mpu-process"></a>

分段上传分为三个步骤：开始上传、上传对象分段，以及在上传所有分段后完成分段上传。在收到完成分段上传请求后，Amazon S3 会利用上传的分段构造对象，而您可以像访问您存储桶中的任何其它对象一样访问该对象。

您可以列出所有正在执行的分段上传，或者获取为特定分段上传操作上传的分段列表。以上每个操作都在本节中进行了说明。

**分段上传开始**  
当您发送请求以开始分段上传时，请确保指定校验和类型。然后，Amazon S3 将返回具有上传 ID 的响应，此 ID 是分段上传的唯一标识符。当您上传分段、列出分段、完成上传或停止上传时，需要此上传 ID。如果您想要提供描述正上传的对象的元数据，必须在请求中提供它以便开始分段上传。匿名用户无法发起分段上传。

**分段上传**  
上传分段时，除了上传 ID 之外，还必须指定分段编号。您可以选择 1 和 10000 之间的任意分段编号。分段编号在您正在上传的对象中唯一地识别分段及其位置。您选择的分段编号不必是连续序列（例如，它可以是 1、5 和 14）。请注意，如果您使用之前上传的分段的同一分段编号上传新分段，则之前上传的分段会被覆盖。

当您上传分段时，Amazon S3 将在响应中返回校验和算法类型，其中每个分段的校验和值作为标头。对于每个分段上传，您必须记录分段编号和 ETag 值。您必须在随后的请求中包括这些值以完成分段上传。每个分段在上传时都有自己的 ETag。但是，一旦分段上传完成并且合并了所有分段，所有分段都会属于一个 ETag，作为多个校验和的校验和。

**重要**  
启动分段上传并上传一个或多个分段之后，您必须完成或停止分段上传，才能停止因存储已上传的分段而产生费用。只有在完成或停止分段上传*之后*，Amazon S3 才会释放分段存储并停止向您收取分段存储费用。  
停止分段上传后，无法再次使用该上传 ID 上传任何分段。如果分段上传正在进行中，则即使在您停止上传后，它们仍然可能会成功或失败。为了确保释放所有分段使用的所有存储，必须仅在完成所有分段的上传后才停止分段上传。

**分段上传完成**  
完成分段上传时，Amazon S3 通过按升序的分段编号规范化分段来创建对象。如果在*开始分段上传*请求中提供了任何对象元数据，则 Amazon S3 会将该元数据与对象相关联。成功*完成*请求后，分段将不再存在。

*完成分段上传* 请求必须包括上传 ID、分段编号及其相应的 ETag 值的列表。Amazon S3 响应包括可唯一地识别组合对象数据的 ETag。此 ETag 无需成为对象数据的 MD5 哈希。

当您在分段上传期间提供完整的对象校验和时，AWS SDK 会将校验和传递给 Amazon S3，而 S3 会在服务器端验证对象完整性，将其与接收到的值进行比较。然后，如果值匹配，S3 将存储对象。如果这两个值不匹配，Amazon S3 将使请求失败并出现 `BadDigest` 错误。对象的校验和还存储在对象元数据中，您稍后将使用这些元数据来验证对象的数据完整性。

**分段上传调用示例**  
 对于此示例，假设您正在为一个 100 GB 的文件生成分段上传。在这种情况下，您应在整个过程中进行以下 API 调用。总共将有 1002 个 API 调用。
+ 一个用于启动该过程的 `[CreateMultipartUpload](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateMultipartUpload.html)` 调用。
+ 1000 个单独的 `[UploadPart](https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPart.html)` 调用，每次上传一个 100 MB 的分段，总大小为 100 GB。
+ 用于完成该过程的 `[CompleteMultipartUpload](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html)` 调用。

**分段上传列表**  
您可以列出特定分段上传或所有正在进行的分段上传的分段。列出分段操作将返回您已为特定分段上传而上传的分段信息。对于每个列出分段请求，Amazon S3 将返回有关特定分段上传的分段信息，最多为 1000 个分段。如果分段上传中的分段数量超过 1000 个，您必须发送一系列列出分段请求以检索所有分段。请注意，返回的分段列表不包括未完成上传的分段。使用*列出分段上传* 操作，您可以获得正在进行的分段上传的列表。

正在进行的分段上传是已开始但还未完成或停止的上传。每个请求将返回最多 1000 个分段上传。如果正在进行的分段上传超过 1000 个，您必须发送其他请求才能检索剩余的分段上传。仅使用返回的列表进行验证。

**重要**  
发送*完成分段上传* 请求时，请勿使用此列表的结果。相反，当上传分段和 Amazon S3 返回的相应 ETag 值时，请保留您自己的指定分段编号的列表。

## 使用分段上传操作的校验和
<a name="mpuchecksums"></a>

在将对象上传到 Amazon S3 时，可指定校验和算法以供 Amazon S3 使用。默认情况下，AWS SDK 和 S3 控制台对所有对象上传使用一种算法，您可以覆盖该算法。如果您使用的是较旧的 SDK，并且您上传的对象没有指定的校验和，则 Amazon S3 会自动使用 CRC-64/NVME (`CRC64NVME`) 校验和算法。（这也是高效数据完整性验证的推荐选项。） 当使用 CRC-64/NVME 时，Amazon S3 会在多分段或单分段上传完成后计算完整对象的校验和。CRC-64/NVME 校验和算法用于计算整个对象的直接校验和，或每个单独分段的多个校验和的校验和。

在使用分段上传将对象上传到 S3 后，Amazon S3 将计算每个分段或完整对象的校验和值并存储这些值。可以通过以下方式使用 S3 API 或 AWS SDK 来检索校验和值：
+ 对于单个分段，可以使用 [https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html) 或 [https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadObject.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadObject.html)。如果您想在分段上传仍在进行时检索各个分段的校验和值，可以使用 [https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListParts.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListParts.html)。
+ 对于整个对象，可以使用 [https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html)。如果要使用完整对象校验和执行分段上传，请通过指定完整对象校验和类型来使用 [https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateMultipartUpload](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateMultipartUpload) 和 [https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload)。要验证整个对象的校验和值或要确认分段上传中使用的是哪种校验和类型，请使用 [https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListParts.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListParts.html)。

**重要**  
如果您将分段上传与**校验和**结合使用，则上传每个分段（在分段上传中）时的分段编号必须使用连续的分段编号并从 1 开始。使用**校验和**时，如果您尝试使用非连续分段编号完成分段上传请求，Amazon S3 将生成 `HTTP 500 Internal Server` 错误。

 有关校验和如何处理分段上传对象的更多信息，请参阅[在 Amazon S3 中检查对象完整性](checking-object-integrity.md)。

有关用于演示如何使用分段上传以及额外的校验和来上传对象的端到端过程，请参阅[教程：通过分段上传来上传对象并验证其数据完整性](tutorial-s3-mpu-additional-checksums.md)。

## 并发分段上传操作
<a name="distributedmpupload"></a>

在分布式开发环境中，您的应用程序可以同时在同一对象上开始多个更新。您的应用程序可能会使用同一对象键开始多个分段上传。然后，对于其中每个上传，您的应用程序可以上传分段并将完成上传请求发送到 Amazon S3，以创建对象。当存储桶启用了 S3 版本控制时，完成分段上传将始终创建一个新版本。当您在启用版本控制的存储桶中启动使用相同对象键的多个分段上传时，对象的当前版本将由最新（`createdDate`）开始的上传决定。

例如，您在上午 10:00 启动对某个对象的 `CreateMultipartUpload` 请求。然后，您在上午 11:00 提交对同一对象的第二个 `CreateMultipartUpload` 请求。因为第二个请求是最新提交的，所以上午 11:00 的请求所上传的对象将成为当前版本，即使第一个上传是在第二个上传之后完成的，也是如此。对于未启用版本控制的存储桶，在启动分段上传与完成分段上传期间接收的任何其它请求都可能会优先。

另一个可以优先处理并发分段上传请求的例子是，在使用某个键开始分段上传之后，其它操作删除了该键。在完成此操作之前，完成分段上传的响应可能表示在未看到对象的情况下成功创建了对象。

## 防止在分段上传期间上传具有相同键名称的对象
<a name="multipart-upload-objects-with-same-key-name"></a>

在对上传操作使用有条件写入来创建对象之前，您可以检查存储桶中是否存在该对象。这样可以防止覆盖现有数据。当上传时，有条件写入将验证存储桶中尚不存在具有相同键名称的现有对象。

可以将有条件写入用于 [https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html) 或 [CompleteMultipartUpload](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html) 请求。

有关有条件请求的更多信息，请参阅[使用有条件请求向 S3 操作添加前提条件](conditional-requests.md)。

## 分段上传和定价
<a name="mpuploadpricing"></a>

开始分段上传后，Amazon S3 将保留所有分段，直到您完成或停止上传。在整个其生命周期内，您将支付有关此分段上传及其关联分段的所有存储、带宽和请求的费用。

将根据在上传各个分段时指定的存储类对这些分段收费。但是，如果将这些分段上传到 S3 Glacier Flexible Retrieval 或 S3 Glacier Deep Archive，则无需为这些分段付费。在上传完成之前，针对 S3 Glacier Flexible Retrieval 存储类的 PUT 请求的正在上传的分段采用 S3 Standard 存储费率按 S3 Glacier Flexible Retrieval 暂存存储计费。此外，`CreateMultipartUpload` 和 `UploadPart` 均按 S3 Standard 费率计费。只有 `CompleteMultipartUpload` 请求按 S3 Glacier Flexible Retrieval 费率计费。同样，在上传完成之前，针对 S3 Glacier Deep Archive 存储类的 PUT 请求的正在上传的分段采用 S3 Standard 存储费率按 S3 Glacier Flexible Retrieval 暂存存储计费，而只有 `CompleteMultipartUpload` 请求按 S3 Glacier Deep Archive 费率计费。

如果您停止分段上传，Amazon S3 将删除上传构件和已上传的任何分段。您无需为这些构件付费。无论指定的存储类如何，删除未完成的分段上传均不收取提前删除费用。有关定价的更多信息，请参阅 [Amazon S3 定价](https://aws.amazon.com/s3/pricing/)。

**注意**  
为了最大程度地降低存储成本，我们建议您配置生命周期规则，以便使用 `AbortIncompleteMultipartUpload` 操作在指定的天数后删除未完成的分段上传。有关创建生命周期规则以删除未完成的分段上传的更多信息，请参阅[配置存储桶生命周期配置以删除未完成的分段上传](https://docs.aws.amazon.com/AmazonS3/latest/userguide/mpu-abort-incomplete-mpu-lifecycle-config.html)。

## 分段上传的 API 支持
<a name="apisupportformpu"></a>

*Amazon Simple Storage Service API 参考*的下面几节描述了适用于分段上传的 REST API。

有关使用 AWS Lambda 函数的分段上传演练，请参阅 [Uploading large objects to Amazon S3 using multipart upload and transfer acceleration](https://aws.amazon.com/blogs/compute/uploading-large-objects-to-amazon-s3-using-multipart-upload-and-transfer-acceleration/)。
+ [创建分段上传](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateMultipartUpload.html)
+ [上传分段](https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPart.html)
+ [上传分段（复制）](https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPartCopy.html)
+ [完成分段上传](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html)
+ [中止分段上传](https://docs.aws.amazon.com/AmazonS3/latest/API/API_AbortMultipartUpload.html)
+ [列出分段](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListParts.html)
+ [列出分段上传](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListMultipartUploads.html)

## AWS Command Line Interface 对于分段上传的支持
<a name="clisupportformpu"></a>

AWS Command Line Interface 中的以下主题介绍了适用于分段上传的操作。
+ [开始分段上传](https://docs.aws.amazon.com/cli/latest/reference/s3api/create-multipart-upload.html)
+ [上传分段](https://docs.aws.amazon.com/cli/latest/reference/s3api/upload-part.html)
+ [上传分段（复制）](https://docs.aws.amazon.com/cli/latest/reference/s3api/upload-part-copy.html)
+ [完成分段上传](https://docs.aws.amazon.com/cli/latest/reference/s3api/complete-multipart-upload.html)
+ [中止分段上传](https://docs.aws.amazon.com/cli/latest/reference/s3api/abort-multipart-upload.html)
+ [列出分段](https://docs.aws.amazon.com/cli/latest/reference/s3api/list-parts.html)
+ [列出分段上传](https://docs.aws.amazon.com/cli/latest/reference/s3api/list-multipart-uploads.html)

## AWS SDK 对于分段上传的支持
<a name="sdksupportformpu"></a>



您可以使用 AWS SDK 分段上传对象。有关 API 操作支持的 AWS SDK 的列表，请参阅：
+ [创建分段上传](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateMultipartUpload.html)
+ [上传分段](https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPart.html)
+ [上传分段（复制）](https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPartCopy.html)
+ [完成分段上传](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html)
+ [中止分段上传](https://docs.aws.amazon.com/AmazonS3/latest/API/API_AbortMultipartUpload.html)
+ [列出分段](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListParts.html)
+ [列出分段上传](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListMultipartUploads.html)

## 分段上传 API 和权限
<a name="mpuAndPermissions"></a>

您必须具有使用分段上传操作的所需权限。您可以使用访问控制列表（ACL）、存储桶策略或用户策略来授予个人执行这些操作的权限。下表列出了使用 ACL、存储桶策略或用户策略时，各种分段上传操作的所需权限。


| 操作 | 所需权限 | 
| --- | --- | 
|  创建分段上传  |  必须支持您对于对象执行 `s3:PutObject` 操作，才能创建分段上传请求。 存储桶拥有者可以允许其他主体执行 `s3:PutObject` 操作。  | 
|  开始分段上传  |  必须支持您对于对象执行 `s3:PutObject` 操作，才能发起分段上传。 存储桶拥有者可以允许其他主体执行 `s3:PutObject` 操作。  | 
| 发起者 | 标识分段上传发起者的容器元素。如果发起者是 AWS 账户，此元素将提供与 Owner 元素相同的信息。如果发起者是 IAM 用户，此元素将提供用户 ARN 和显示名称。 | 
| 上传分段 | 必须允许您对对象执行 `s3:PutObject` 操作，才能上传分段。 存储桶拥有者必须允许发起者对对象执行 `s3:PutObject` 操作，以便发起者可以上传该对象的分段。 | 
| 上传分段（复制） | 必须允许您对对象执行 `s3:PutObject` 操作，才能上传分段。因为您正在上传现有对象的分段，因此必须允许您对源对象执行 `s3:GetObject`。 存储桶拥有者必须允许发起者对对象执行 `s3:PutObject` 操作，发起者才能上传该对象的分段。 | 
| 完成分段上传 | 必须允许您对对象执行 `s3:PutObject` 操作，才能完成分段上传。 存储桶拥有者必须允许发起者对对象执行 `s3:PutObject` 操作，以便发起者可以完成该对象的分段上传。 | 
| 停止分段上传 | 必须允许您执行 `s3:AbortMultipartUpload` 操作，才能停止分段上传。 默认情况下，支持存储桶拥有者和分段上传的发起者执行此操作，作为 IAM 和 S3 存储桶策略的一部分。如果发起者是 IAM 用户，也允许该用户的 AWS 账户停止此分段上传。使用 VPC 端点策略，分段上传的发起者不会自动获得执行 `s3:AbortMultipartUpload` 操作的权限。 除了这些默认情况之外，存储桶拥有者可以允许其他主体对对象执行 `s3:AbortMultipartUpload` 操作。存储桶拥有者可以拒绝任何主体，使其无法执行 `s3:AbortMultipartUpload` 操作。 | 
| 列出分段 | 您必须得到可以执行 `s3:ListMultipartUploadParts` 操作的允许，才能在分段上传中列出分段。 在默认情况下，存储桶拥有者有权为任何针对存储桶的分段上传列出分段。分段上传的发起者有权为特定分段上传列出分段。如果分段上传的发起者是 IAM 用户，则控制该 IAM 用户的 AWS 账户 同样有权列出此次上传的分段。  除了这些默认情况之外，存储桶拥有者可以允许其他主体对对象执行 `s3:ListMultipartUploadParts` 操作。存储桶拥有者也可以拒绝任何主体，使其无法执行 `s3:ListMultipartUploadParts` 操作。 | 
| 列出分段上传 | 您必须得到可以对存储桶执行 `s3:ListBucketMultipartUploads` 操作的允许，才能列出正在上传到该存储桶的分段上传。 除了默认情况之外，存储桶拥有者可以允许其他主体对存储桶执行 `s3:ListBucketMultipartUploads` 操作。 | 
| AWS KMS 加密和解密相关权限 |  要通过采用 AWS Key Management Service（AWS KMS）KMS 密钥的加密执行分段上传，请求者必须具有以下权限： [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/AmazonS3/latest/userguide/mpuoverview.html)  这些权限是必需的，因为 Amazon S3 必须在完成分段上传之前解密并读取加密的文件段中的数据。要获得对象的校验和值，还需要 `kms:Decrypt` 权限以及具有客户提供的加密密钥的服务器端加密。如果您在使用 [https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html) API 时没有这些必需的权限，则将在没有校验和的情况下创建对象。 如果 IAM 用户或角色与 KMS 密钥位于相同的 AWS 账户中，则验证您对密钥和 IAM 策略都拥有权限。如果您的 IAM 用户或角色属于与 KMS 密钥不同的账户，您必须在密钥策略和 IAM 用户或角色中具有这些权限。  | 
| SSE-C（具有客户提供的加密密钥的服务器端加密） | 使用 [https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html) API 时，必须提供 SSE-C（具有客户提供的加密密钥的服务器端加密），否则将在没有校验和的情况下创建对象，并且不会返回校验和值。  | 

有关 ACL 权限与访问策略中的权限之间关系的信息，请参阅 [ACL 权限和访问策略权限的映射](acl-overview.md#acl-access-policy-permission-mapping)。有关 IAM 用户、角色和最佳实践的信息，请参阅《IAM 用户指南》**中的 [IAM 身份（用户、用户组和角色）](https://docs.aws.amazon.com/IAM/latest/UserGuide/id.html)。

## 使用分段上传操作的校验和
<a name="Checksums-mpu-operations"></a>

有三个 Amazon S3 API 用于执行实际的分段上传：[https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateMultipartUpload.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateMultipartUpload.html)、[https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPart.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPart.html) 和 [https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html)。下表指出了必须为其中每个 API 提供哪些校验和标头和值：


| 校验和算法 | 校验和类型 | `CreateMultipartUpload` | `UploadPart` | `CompleteMultipartUpoad` | 
| --- | --- | --- | --- | --- | 
| CRC-64/NVME (`CRC64NVME`) | 完整对象 | 必需的标头：`x-amz-checksum-algorithm` |  可选标头： `x-amz-checksum-crc64nvme`  |  可选标头： `x-amz-checksum-algorithm` `x-amz-crc64`  | 
| CRC-32 (`CRC32`) CRC 32-C (`CRC32C`) | 完整对象 |  必需的标头： `x-amz-checksum-algorithm` `x-amz-checksum-type`  |  可选标头： `x-amz-checksum-crc64nvme`  |  可选标头： `x-amz-checksum-algorithm` `x-amz-crc32` `x-amz-crc32c`  | 
|  CRC-32 (`CRC32`) CRC-32C (`CRC32C`) SHA-1 (`SHA1`) SHA-256 (`SHA256`) | 复合键 |  必需的标头： `x-amz-checksum-algorithm`  |  必需的标头： `x-amz-checksum-crc32` `x-amz-checksum-crc32c` `x-amz-checksum-sha1` `x-amz-checksum-sha256`  |  必需的标头： 所有分段级的校验和都需要包含在 `CompleteMultiPartUpload` 请求中。 可选标头： `x-amz-crc32` `x-amz-crc32c` `x-amz-sha1` `x-amz-sha256`  | 

**Topics**
+ [

## 分段上传流程
](#mpu-process)
+ [

## 使用分段上传操作的校验和
](#mpuchecksums)
+ [

## 并发分段上传操作
](#distributedmpupload)
+ [

## 防止在分段上传期间上传具有相同键名称的对象
](#multipart-upload-objects-with-same-key-name)
+ [

## 分段上传和定价
](#mpuploadpricing)
+ [

## 分段上传的 API 支持
](#apisupportformpu)
+ [

## AWS Command Line Interface 对于分段上传的支持
](#clisupportformpu)
+ [

## AWS SDK 对于分段上传的支持
](#sdksupportformpu)
+ [

## 分段上传 API 和权限
](#mpuAndPermissions)
+ [

## 使用分段上传操作的校验和
](#Checksums-mpu-operations)
+ [

# 配置存储桶生命周期配置以删除未完成的分段上传
](mpu-abort-incomplete-mpu-lifecycle-config.md)
+ [

# 使用分段上传操作上传对象
](mpu-upload-object.md)
+ [

# 使用高级别 .NET TransferUtility 类上传目录。
](HLuploadDirDotNet.md)
+ [

# 列出分段上传
](list-mpu.md)
+ [

# 使用 AWS SDK 跟踪分段上传
](track-mpu.md)
+ [

# 中止分段上传
](abort-mpu.md)
+ [

# 使用分段上传复制对象
](CopyingObjectsMPUapi.md)
+ [

# 教程：通过分段上传来上传对象并验证其数据完整性
](tutorial-s3-mpu-additional-checksums.md)
+ [

# Amazon S3 分段上传限制
](qfacts.md)

# 配置存储桶生命周期配置以删除未完成的分段上传
<a name="mpu-abort-incomplete-mpu-lifecycle-config"></a>

作为最佳实践，我们建议您使用 `AbortIncompleteMultipartUpload` 操作配置生命周期规则，以最大程度地降低存储成本。有关中止分段上传的更多信息，请参阅 [中止分段上传](abort-mpu.md)。

Amazon S3 支持存储桶生命周期规则，您可以使用该规则指示 Amazon S3 停止未在启动后的指定天数内完成的分段上传。如果分段上传未在指定的时间范围内完成，则符合中止操作的条件。然后，Amazon S3 停止分段上传，并删除与分段上传关联的分段。此规则既适用于现有的分段上传，也适用于您后续创建的分段上传。

 下面是使用 `AbortIncompleteMultipartUpload` 操作指定规则的示例生命周期配置。

```
<LifecycleConfiguration>
    <Rule>
        <ID>sample-rule</ID>
        <Prefix></Prefix>
        <Status>Enabled</Status>
        <AbortIncompleteMultipartUpload>
          <DaysAfterInitiation>7</DaysAfterInitiation>
        </AbortIncompleteMultipartUpload>
    </Rule>
</LifecycleConfiguration>
```

在本示例中，该规则不为 `Prefix` 元素（[对象键名称前缀](https://docs.aws.amazon.com/general/latest/gr/glos-chap.html#keyprefix)）指定值。因此，该规则适用于您启动了分段上传的存储桶中的所有对象。任何已启动但未在七天内完成的分段上传都符合执行中止操作的条件。中止操作对已完成的分段上传没有任何效果。

有关存储桶生命周期配置的更多信息，请参阅 [管理对象的生命周期](object-lifecycle-mgmt.md)。

**注意**  
如果分段上传在规则中指定的天数内完成，则 `AbortIncompleteMultipartUpload` 生命周期操作不适用（即，Amazon S3 不会执行任何操作）。此外，此操作不适用于对象。此生命周期操作不会删除任何对象。此外，当您删除任何未完成的分段上传分段时，不会收取 S3 生命周期的提前删除费用。

## 使用 S3 控制台
<a name="mpu-abort-incomplete-mpu-lifecycle-config-console"></a>

要自动管理未完成的分段上传，您可以使用 S3 控制台创建生命周期规则，以使存储桶中的未完成分段上传字节在指定天数后过期。以下过程介绍如何添加生命周期规则，以在 7 天后删除未完成的分段上传。有关添加生命周期规则的更多信息，请参阅[在存储桶上设置 S3 生命周期配置](how-to-set-lifecycle-configuration-intro.md)。

**添加生命周期规则以中止超过 7 天的未完成的分段上传**

1. 登录到 AWS 管理控制台，然后通过以下网址打开 Amazon S3 控制台：[https://console.aws.amazon.com/s3/](https://console.aws.amazon.com/s3/)。

1. 在 **Buckets（存储桶）**列表中，请选择要为其创建生命周期规则的存储桶的名称。

1. 请选择 **Management（管理）**选项卡，然后选择 **Create lifecycle rule（创建生命周期规则）**。

1. 在 **Lifecycle rule name (生命周期规则名称)** 中，输入规则的名称。

   在该存储桶内，此名称必须是唯一的。

1. 请选择生命周期规则的范围：
   + 要为具有特定前缀的所有对象创建生命周期规则，请选择 **Limit the scope of this rule using one or more filters**（使用一个或多个筛选条件限制此规则的范围），然后在 **Prefix**（前缀）字段中输入前缀。
   + 要为存储桶中的所有对象创建生命周期规则，请选择 **This rule applies to **all** objects in the bucket**（此规则适用于存储桶中的所有对象），然后选择 **I acknowledge that this rule applies to all objects in the bucket**（我确认此规则适用于存储桶中的所有对象）。

1. 在 **Lifecycle rule actions**（生命周期规则操作）下，选择 **Delete expired object delete markers or incomplete multipart uploads**（删除过期的对象删除标记或未完成的分段上传）。

1. 在 **Delete expired object delete markers or incomplete multipart uploads**（删除过期的对象删除标记或未完成的分段上传）下，选择 **Delete incomplete multipart uploads**（删除未完成的分段上传）。

1. 在 **Number of days**（天数）字段中，输入天数，在此天数之后将删除未完成的分段上传（在本例中为 7 天）。

1. 选择**创建规则**。

## 使用 AWS CLI
<a name="mpu-abort-incomplete-mpu-lifecycle-config-cli"></a>

以下 `put-bucket-lifecycle-configuration` AWS Command Line Interface（AWS CLI）命令为指定的存储桶添加生命周期配置。要使用此命令，请将 `user input placeholders` 替换为您的信息。

```
aws s3api put-bucket-lifecycle-configuration  \
        --bucket amzn-s3-demo-bucket  \
        --lifecycle-configuration filename-containing-lifecycle-configuration
```

以下示例显示如何使用 AWS CLI 添加生命周期规则以中止未完成的分段上传。它包括一个示例 JSON 生命周期配置，以中止超过 7 天的未完成的分段上传。

要使用本示例中的 CLI 命令，请将 `user input placeholders` 替换为您的信息。

**添加生命周期规则以中止未完成的分段上传**

1. 设置 AWS CLI。有关说明，请参阅《Amazon S3 API 参考》**中的 [Developing with Amazon S3 using the AWS CLI](https://docs.aws.amazon.com/AmazonS3/latest/API/setup-aws-cli.html)。

1. 将以下示例生命周期配置保存在一个文件（例如 *`lifecycle.json`*``）中。该示例配置指定了空前缀，因此它适用于存储桶中的所有对象。为将配置限制为某个对象子集，您可以指定前缀。

   ```
   {
       "Rules": [
           {
               "ID": "Test Rule",
               "Status": "Enabled",
               "Filter": {
                   "Prefix": ""
               },
               "AbortIncompleteMultipartUpload": {
                   "DaysAfterInitiation": 7
               }
           }
       ]
   }
   ```

1.  运行以下 CLI 命令以在存储桶上设置此生命周期配置。

   ```
   aws s3api put-bucket-lifecycle-configuration   \
   --bucket amzn-s3-demo-bucket  \
   --lifecycle-configuration file://lifecycle.json
   ```

1.  要验证是否已在您的存储桶上设置了生命周期配置，请使用以下 `get-bucket-lifecycle` 命令检索生命周期配置。

   ```
   aws s3api get-bucket-lifecycle  \
   --bucket amzn-s3-demo-bucket
   ```

1.  要删除生命周期配置，请使用以下 `delete-bucket-lifecycle` 命令。

   ```
   aws s3api delete-bucket-lifecycle \
   --bucket amzn-s3-demo-bucket
   ```

# 使用分段上传操作上传对象
<a name="mpu-upload-object"></a>

您可以使用分段上传以编程方式将单个对象上传到 Amazon S3。每个对象作为一组分段进行上传。每个分段都是对象数据的连续部分。您可以独立上传以及按任意顺序上传这些对象分段。如果任意分段传输失败，可以重新传输该分段且不会影响其他分段。上传完所有的对象分段后，Amazon S3 将汇集这些分段并创建对象。匿名用户无法发起分段上传。

有关使用分段上传以及额外的校验和来上传对象的端到端过程，请参阅[教程：通过分段上传来上传对象并验证其数据完整性](tutorial-s3-mpu-additional-checksums.md)。

下一节介绍如何通过 AWS Command Line Interface和 AWS SDK 使用分段上传。

## 使用 S3 控制台
<a name="MultipartUploadConsole"></a>

您可以将任何类型的文件上传至 S3 存储桶，包括图像、备份、数据、电影等。可使用 Amazon S3 控制台上传的文件的最大大小为 160 GB。要上传大于 160GB 的文件，请使用 AWS Command Line Interface（AWS CLI）、AWS SDK 或 Amazon S3 REST API。

有关通过 AWS 管理控制台上传对象的说明，请参阅[上传对象](upload-objects.md)。

## 使用 AWS CLI
<a name="UsingCLImpUpload"></a>

以下内容介绍使用 AWS CLI 进行分段上传的 Amazon S3 操作。
+ [开始分段上传](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3api/create-multipart-upload.html)
+ [上传分段](https://docs.aws.amazon.com/cli/latest/reference/s3api/upload-part.html)
+ [上传分段（复制）](https://docs.aws.amazon.com/cli/latest/reference/s3api/upload-part-copy.html)
+ [完成分段上传](https://docs.aws.amazon.com/cli/latest/reference/s3api/complete-multipart-upload.html)
+ [中止分段上传](https://docs.aws.amazon.com/cli/latest/reference/s3api/abort-multipart-upload.html)
+ [列出分段](https://docs.aws.amazon.com/cli/latest/reference/s3api/list-parts.html)
+ [列出分段上传](https://docs.aws.amazon.com/cli/latest/reference/s3api/list-multipart-uploads.html)

## 使用 REST API
<a name="UsingRESTAPImpUpload"></a>

*Amazon Simple Storage Service API 参考*的下面几节描述了适用于分段上传的 REST API。
+ [开始分段上传](https://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadInitiate.html)
+ [上传分段](https://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadUploadPart.html)
+ [完成分段上传](https://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadComplete.html)
+ [停止分段上传](https://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadAbort.html)
+ [列出分段](https://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadListParts.html)
+ [列出分段上传](https://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadListMPUpload.html)

## 使用 AWS SDK（高级别 API）
<a name="multipart-upload-high-level"></a>

一些 AWS SDK 公开了一个高级别 API，该 API 通过将完成分段上传所需的不同 API 操作组合成单个操作，来简化分段上传。有关更多信息，请参阅 [在 Amazon S3 中使用分段上传来上传和复制对象](mpuoverview.md)。

如果您需要暂停并恢复分段上传、在上传期间改变分段大小，或者事先不知道数据大小，请使用低级别 API 方法。用于分段上传的低级别 API 方法提供了额外功能，有关更多信息，请参阅[使用 AWS SDK（低级别 API）](#mpu-upload-low-level)。

------
#### [ Java ]

有关如何使用适用于 Java 的 AWS SDK 执行分段上传的示例，请参阅《Amazon S3 API Reference》**中的 [Upload or download large files to and from Amazon S3 using an AWS SDK](https://docs.aws.amazon.com/AmazonS3/latest/API/s3_example_s3_Scenario_UsingLargeFiles_section.html)。

------
#### [ .NET ]

要将文件上传到 S3 存储桶，请使用 `TransferUtility` 类。在从文件上传数据时，您必须提供对象的键名。如果未提供，该 API 将使用文件名作为键名。在从流上传数据时，您必须提供对象的键名。

要设置高级上传选项（如段大小、并发上传段时的线程数、元数据、存储类或 ACL），请使用 `TransferUtilityUploadRequest` 类。

**注意**  
如果您将流用作数据源，`TransferUtility` 类不会执行并发上传。

以下 C\$1 示例将文件分段上传到 Amazon S3 存储桶。它说明如何使用各种 `TransferUtility.Upload` 重载来上传文件。每个对上传的后续调用都将替换先前的上传。有关设置和运行代码示例的信息，请参阅《适用于 .NET 的 AWS SDK 开发人员指南》**中的[适用于 .NET 的 AWS SDK 入门](https://docs.aws.amazon.com/sdk-for-net/latest/developer-guide/net-dg-setup.html)。

```
using Amazon;
using Amazon.S3;
using Amazon.S3.Transfer;
using System;
using System.IO;
using System.Threading.Tasks;

namespace Amazon.DocSamples.S3
{
    class UploadFileMPUHighLevelAPITest
    {
        private const string bucketName = "*** provide bucket name ***";
        private const string keyName = "*** provide a name for the uploaded object ***";
        private const string filePath = "*** provide the full path name of the file to upload ***";
        // Specify your bucket region (an example region is shown).
        private static readonly RegionEndpoint bucketRegion = RegionEndpoint.USWest2;
        private static IAmazonS3 s3Client;

        public static void Main()
        {
            s3Client = new AmazonS3Client(bucketRegion);
            UploadFileAsync().Wait();
        }

        private static async Task UploadFileAsync()
        {
            try
            {
                var fileTransferUtility =
                    new TransferUtility(s3Client);

                // Option 1. Upload a file. The file name is used as the object key name.
                await fileTransferUtility.UploadAsync(filePath, bucketName);
                Console.WriteLine("Upload 1 completed");

                // Option 2. Specify object key name explicitly.
                await fileTransferUtility.UploadAsync(filePath, bucketName, keyName);
                Console.WriteLine("Upload 2 completed");

                // Option 3. Upload data from a type of System.IO.Stream.
                using (var fileToUpload = 
                    new FileStream(filePath, FileMode.Open, FileAccess.Read))
                {
                    await fileTransferUtility.UploadAsync(fileToUpload,
                                               bucketName, keyName);
                }
                Console.WriteLine("Upload 3 completed");

                // Option 4. Specify advanced settings.
                var fileTransferUtilityRequest = new TransferUtilityUploadRequest
                {
                    BucketName = bucketName,
                    FilePath = filePath,
                    StorageClass = S3StorageClass.StandardInfrequentAccess,
                    PartSize = 6291456, // 6 MB.
                    Key = keyName,
                    CannedACL = S3CannedACL.PublicRead
                };
                fileTransferUtilityRequest.Metadata.Add("param1", "Value1");
                fileTransferUtilityRequest.Metadata.Add("param2", "Value2");

                await fileTransferUtility.UploadAsync(fileTransferUtilityRequest);
                Console.WriteLine("Upload 4 completed");
            }
            catch (AmazonS3Exception e)
            {
                Console.WriteLine("Error encountered on server. Message:'{0}' when writing an object", e.Message);
            }
            catch (Exception e)
            {
                Console.WriteLine("Unknown encountered on server. Message:'{0}' when writing an object", e.Message);
            }

        }
    }
}
```

------
#### [ JavaScript ]

**Example**  
上传大文件。  

```
import { S3Client } from "@aws-sdk/client-s3";
import { Upload } from "@aws-sdk/lib-storage";

import {
  ProgressBar,
  logger,
} from "@aws-doc-sdk-examples/lib/utils/util-log.js";

const twentyFiveMB = 25 * 1024 * 1024;

export const createString = (size = twentyFiveMB) => {
  return "x".repeat(size);
};

/**
 * Create a 25MB file and upload it in parts to the specified
 * Amazon S3 bucket.
 * @param {{ bucketName: string, key: string }}
 */
export const main = async ({ bucketName, key }) => {
  const str = createString();
  const buffer = Buffer.from(str, "utf8");
  const progressBar = new ProgressBar({
    description: `Uploading "${key}" to "${bucketName}"`,
    barLength: 30,
  });

  try {
    const upload = new Upload({
      client: new S3Client({}),
      params: {
        Bucket: bucketName,
        Key: key,
        Body: buffer,
      },
    });

    upload.on("httpUploadProgress", ({ loaded, total }) => {
      progressBar.update({ current: loaded, total });
    });

    await upload.done();
  } catch (caught) {
    if (caught instanceof Error && caught.name === "AbortError") {
      logger.error(`Multipart upload was aborted. ${caught.message}`);
    } else {
      throw caught;
    }
  }
};
```

**Example**  
下载大文件。  

```
import { fileURLToPath } from "node:url";
import { GetObjectCommand, NoSuchKey, S3Client } from "@aws-sdk/client-s3";
import { createWriteStream, rmSync } from "node:fs";

const s3Client = new S3Client({});
const oneMB = 1024 * 1024;

export const getObjectRange = ({ bucket, key, start, end }) => {
  const command = new GetObjectCommand({
    Bucket: bucket,
    Key: key,
    Range: `bytes=${start}-${end}`,
  });

  return s3Client.send(command);
};

/**
 * @param {string | undefined} contentRange
 */
export const getRangeAndLength = (contentRange) => {
  const [range, length] = contentRange.split("/");
  const [start, end] = range.split("-");
  return {
    start: Number.parseInt(start),
    end: Number.parseInt(end),
    length: Number.parseInt(length),
  };
};

export const isComplete = ({ end, length }) => end === length - 1;

const downloadInChunks = async ({ bucket, key }) => {
  const writeStream = createWriteStream(
    fileURLToPath(new URL(`./${key}`, import.meta.url)),
  ).on("error", (err) => console.error(err));

  let rangeAndLength = { start: -1, end: -1, length: -1 };

  while (!isComplete(rangeAndLength)) {
    const { end } = rangeAndLength;
    const nextRange = { start: end + 1, end: end + oneMB };

    const { ContentRange, Body } = await getObjectRange({
      bucket,
      key,
      ...nextRange,
    });
    console.log(`Downloaded bytes ${nextRange.start} to ${nextRange.end}`);

    writeStream.write(await Body.transformToByteArray());
    rangeAndLength = getRangeAndLength(ContentRange);
  }
};

/**
 * Download a large object from and Amazon S3 bucket.
 *
 * When downloading a large file, you might want to break it down into
 * smaller pieces. Amazon S3 accepts a Range header to specify the start
 * and end of the byte range to be downloaded.
 *
 * @param {{ bucketName: string, key: string }}
 */
export const main = async ({ bucketName, key }) => {
  try {
    await downloadInChunks({
      bucket: bucketName,
      key: key,
    });
  } catch (caught) {
    if (caught instanceof NoSuchKey) {
      console.error(`Failed to download object. No such key "${key}".`);
      rmSync(key);
    }
  }
};
```

------
#### [ Go ]

有关分段上传的 Go 代码示例的更多信息，请参阅 [Upload or download large files to and from Amazon S3 using an AWS SDK](https://docs.aws.amazon.com/AmazonS3/latest/API/s3_example_s3_Scenario_UsingLargeFiles_section.html)。

**Example**  
使用上传管理器上传大型对象，以将数据分成多个分段，然后同时上传。  

```
import (
	"bytes"
	"context"
	"errors"
	"fmt"
	"io"
	"log"
	"os"
	"time"

	"github.com/aws/aws-sdk-go-v2/aws"
	"github.com/aws/aws-sdk-go-v2/feature/s3/manager"
	"github.com/aws/aws-sdk-go-v2/service/s3"
	"github.com/aws/aws-sdk-go-v2/service/s3/types"
	"github.com/aws/smithy-go"
)

// BucketBasics encapsulates the Amazon Simple Storage Service (Amazon S3) actions
// used in the examples.
// It contains S3Client, an Amazon S3 service client that is used to perform bucket
// and object actions.
type BucketBasics struct {
	S3Client *s3.Client
}
```

```
// UploadLargeObject uses an upload manager to upload data to an object in a bucket.
// The upload manager breaks large data into parts and uploads the parts concurrently.
func (basics BucketBasics) UploadLargeObject(ctx context.Context, bucketName string, objectKey string, largeObject []byte) error {
	largeBuffer := bytes.NewReader(largeObject)
	var partMiBs int64 = 10
	uploader := manager.NewUploader(basics.S3Client, func(u *manager.Uploader) {
		u.PartSize = partMiBs * 1024 * 1024
	})
	_, err := uploader.Upload(ctx, &s3.PutObjectInput{
		Bucket: aws.String(bucketName),
		Key:    aws.String(objectKey),
		Body:   largeBuffer,
	})
	if err != nil {
		var apiErr smithy.APIError
		if errors.As(err, &apiErr) && apiErr.ErrorCode() == "EntityTooLarge" {
			log.Printf("Error while uploading object to %s. The object is too large.\n"+
				"The maximum size for a multipart upload is 5TB.", bucketName)
		} else {
			log.Printf("Couldn't upload large object to %v:%v. Here's why: %v\n",
				bucketName, objectKey, err)
		}
	} else {
		err = s3.NewObjectExistsWaiter(basics.S3Client).Wait(
			ctx, &s3.HeadObjectInput{Bucket: aws.String(bucketName), Key: aws.String(objectKey)}, time.Minute)
		if err != nil {
			log.Printf("Failed attempt to wait for object %s to exist.\n", objectKey)
		}
	}

	return err
}
```

**Example**  
使用下载管理器下载大型对象，以分段获取数据并同时下载它们。  

```
// DownloadLargeObject uses a download manager to download an object from a bucket.
// The download manager gets the data in parts and writes them to a buffer until all of
// the data has been downloaded.
func (basics BucketBasics) DownloadLargeObject(ctx context.Context, bucketName string, objectKey string) ([]byte, error) {
	var partMiBs int64 = 10
	downloader := manager.NewDownloader(basics.S3Client, func(d *manager.Downloader) {
		d.PartSize = partMiBs * 1024 * 1024
	})
	buffer := manager.NewWriteAtBuffer([]byte{})
	_, err := downloader.Download(ctx, buffer, &s3.GetObjectInput{
		Bucket: aws.String(bucketName),
		Key:    aws.String(objectKey),
	})
	if err != nil {
		log.Printf("Couldn't download large object from %v:%v. Here's why: %v\n",
			bucketName, objectKey, err)
	}
	return buffer.Bytes(), err
}
```

------
#### [ PHP ]

本主题介绍如何使用 `Aws\S3\Model\MultipartUpload\UploadBuilder` 中的高级别 适用于 PHP 的 AWS SDK 类执行文件分段上传。有关适用于 Ruby 的 AWS 开发工具包 API 的更多信息，请转到[适用于 Ruby 的 AWS 开发工具包 – 版本 2](https://docs.aws.amazon.com/sdkforruby/api/index.html)。

以下 PHP 代码示例将文件上传到 Amazon S3 存储桶。该示例演示如何设置 `MultipartUploader` 对象的参数。

```
 require 'vendor/autoload.php';

use Aws\Exception\MultipartUploadException;
use Aws\S3\MultipartUploader;
use Aws\S3\S3Client;

$bucket = '*** Your Bucket Name ***';
$keyname = '*** Your Object Key ***';

$s3 = new S3Client([
    'version' => 'latest',
    'region'  => 'us-east-1'
]);

// Prepare the upload parameters.
$uploader = new MultipartUploader($s3, '/path/to/large/file.zip', [
    'bucket' => $bucket,
    'key'    => $keyname
]);

// Perform the upload.
try {
    $result = $uploader->upload();
    echo "Upload complete: {$result['ObjectURL']}" . PHP_EOL;
} catch (MultipartUploadException $e) {
    echo $e->getMessage() . PHP_EOL;
}
```

------
#### [ Python ]

以下示例使用高级别分段上传 Python API（`TransferManager` 类）上传对象。

```
import sys
import threading

import boto3
from boto3.s3.transfer import TransferConfig


MB = 1024 * 1024
s3 = boto3.resource("s3")


class TransferCallback:
    """
    Handle callbacks from the transfer manager.

    The transfer manager periodically calls the __call__ method throughout
    the upload and download process so that it can take action, such as
    displaying progress to the user and collecting data about the transfer.
    """

    def __init__(self, target_size):
        self._target_size = target_size
        self._total_transferred = 0
        self._lock = threading.Lock()
        self.thread_info = {}

    def __call__(self, bytes_transferred):
        """
        The callback method that is called by the transfer manager.

        Display progress during file transfer and collect per-thread transfer
        data. This method can be called by multiple threads, so shared instance
        data is protected by a thread lock.
        """
        thread = threading.current_thread()
        with self._lock:
            self._total_transferred += bytes_transferred
            if thread.ident not in self.thread_info.keys():
                self.thread_info[thread.ident] = bytes_transferred
            else:
                self.thread_info[thread.ident] += bytes_transferred

            target = self._target_size * MB
            sys.stdout.write(
                f"\r{self._total_transferred} of {target} transferred "
                f"({(self._total_transferred / target) * 100:.2f}%)."
            )
            sys.stdout.flush()


def upload_with_default_configuration(
    local_file_path, bucket_name, object_key, file_size_mb
):
    """
    Upload a file from a local folder to an Amazon S3 bucket, using the default
    configuration.
    """
    transfer_callback = TransferCallback(file_size_mb)
    s3.Bucket(bucket_name).upload_file(
        local_file_path, object_key, Callback=transfer_callback
    )
    return transfer_callback.thread_info


def upload_with_chunksize_and_meta(
    local_file_path, bucket_name, object_key, file_size_mb, metadata=None
):
    """
    Upload a file from a local folder to an Amazon S3 bucket, setting a
    multipart chunk size and adding metadata to the Amazon S3 object.

    The multipart chunk size controls the size of the chunks of data that are
    sent in the request. A smaller chunk size typically results in the transfer
    manager using more threads for the upload.

    The metadata is a set of key-value pairs that are stored with the object
    in Amazon S3.
    """
    transfer_callback = TransferCallback(file_size_mb)

    config = TransferConfig(multipart_chunksize=1 * MB)
    extra_args = {"Metadata": metadata} if metadata else None
    s3.Bucket(bucket_name).upload_file(
        local_file_path,
        object_key,
        Config=config,
        ExtraArgs=extra_args,
        Callback=transfer_callback,
    )
    return transfer_callback.thread_info


def upload_with_high_threshold(local_file_path, bucket_name, object_key, file_size_mb):
    """
    Upload a file from a local folder to an Amazon S3 bucket, setting a
    multipart threshold larger than the size of the file.

    Setting a multipart threshold larger than the size of the file results
    in the transfer manager sending the file as a standard upload instead of
    a multipart upload.
    """
    transfer_callback = TransferCallback(file_size_mb)
    config = TransferConfig(multipart_threshold=file_size_mb * 2 * MB)
    s3.Bucket(bucket_name).upload_file(
        local_file_path, object_key, Config=config, Callback=transfer_callback
    )
    return transfer_callback.thread_info


def upload_with_sse(
    local_file_path, bucket_name, object_key, file_size_mb, sse_key=None
):
    """
    Upload a file from a local folder to an Amazon S3 bucket, adding server-side
    encryption with customer-provided encryption keys to the object.

    When this kind of encryption is specified, Amazon S3 encrypts the object
    at rest and allows downloads only when the expected encryption key is
    provided in the download request.
    """
    transfer_callback = TransferCallback(file_size_mb)
    if sse_key:
        extra_args = {"SSECustomerAlgorithm": "AES256", "SSECustomerKey": sse_key}
    else:
        extra_args = None
    s3.Bucket(bucket_name).upload_file(
        local_file_path, object_key, ExtraArgs=extra_args, Callback=transfer_callback
    )
    return transfer_callback.thread_info


def download_with_default_configuration(
    bucket_name, object_key, download_file_path, file_size_mb
):
    """
    Download a file from an Amazon S3 bucket to a local folder, using the
    default configuration.
    """
    transfer_callback = TransferCallback(file_size_mb)
    s3.Bucket(bucket_name).Object(object_key).download_file(
        download_file_path, Callback=transfer_callback
    )
    return transfer_callback.thread_info


def download_with_single_thread(
    bucket_name, object_key, download_file_path, file_size_mb
):
    """
    Download a file from an Amazon S3 bucket to a local folder, using a
    single thread.
    """
    transfer_callback = TransferCallback(file_size_mb)
    config = TransferConfig(use_threads=False)
    s3.Bucket(bucket_name).Object(object_key).download_file(
        download_file_path, Config=config, Callback=transfer_callback
    )
    return transfer_callback.thread_info


def download_with_high_threshold(
    bucket_name, object_key, download_file_path, file_size_mb
):
    """
    Download a file from an Amazon S3 bucket to a local folder, setting a
    multipart threshold larger than the size of the file.

    Setting a multipart threshold larger than the size of the file results
    in the transfer manager sending the file as a standard download instead
    of a multipart download.
    """
    transfer_callback = TransferCallback(file_size_mb)
    config = TransferConfig(multipart_threshold=file_size_mb * 2 * MB)
    s3.Bucket(bucket_name).Object(object_key).download_file(
        download_file_path, Config=config, Callback=transfer_callback
    )
    return transfer_callback.thread_info


def download_with_sse(
    bucket_name, object_key, download_file_path, file_size_mb, sse_key
):
    """
    Download a file from an Amazon S3 bucket to a local folder, adding a
    customer-provided encryption key to the request.

    When this kind of encryption is specified, Amazon S3 encrypts the object
    at rest and allows downloads only when the expected encryption key is
    provided in the download request.
    """
    transfer_callback = TransferCallback(file_size_mb)

    if sse_key:
        extra_args = {"SSECustomerAlgorithm": "AES256", "SSECustomerKey": sse_key}
    else:
        extra_args = None
    s3.Bucket(bucket_name).Object(object_key).download_file(
        download_file_path, ExtraArgs=extra_args, Callback=transfer_callback
    )
    return transfer_callback.thread_info
```

------

## 使用 AWS SDK（低级别 API）
<a name="mpu-upload-low-level"></a>

AWS SDK 公开了一个与 Amazon S3 REST API 非常相似的用于分段上传的低级别 API（请参阅[在 Amazon S3 中使用分段上传来上传和复制对象](mpuoverview.md)）。当您需要暂停和恢复分段上传、在上传过程中更改部分大小或事先不知道上传数据的大小时，请使用低级别 API。当您没有这些需求时，请使用高级别 API（请参阅[使用 AWS SDK（高级别 API）](#multipart-upload-high-level)）。

------
#### [ Java ]

以下示例演示如何使用低级别 Java 类上传文件。它将执行以下步骤：
+ 使用 `AmazonS3Client.initiateMultipartUpload()` 方法初始化分段上传，并传入 `InitiateMultipartUploadRequest` 对象。
+ 保存 `AmazonS3Client.initiateMultipartUpload()` 方法返回的上传 ID。您为随后的每个分段上传操作提供此上传 ID。
+ 上传对象的分段。对于每个分段，您将调用 `AmazonS3Client.uploadPart()` 方法。您使用 `UploadPartRequest` 对象提供分段上传信息。
+ 对于每个分段，在列表中保存来自 `AmazonS3Client.uploadPart()` 方法的响应的 ETag。您使用 ETag 值完成分段上传。
+ 调用 `AmazonS3Client.completeMultipartUpload()` 方法来完成分段上传。

**Example**  
有关创建和测试有效示例的说明，请参阅《适用于 Java 的 AWS SDK 开发人员指南》中的[入门](https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/getting-started.html)。  

```
import com.amazonaws.AmazonServiceException;
import com.amazonaws.SdkClientException;
import com.amazonaws.auth.profile.ProfileCredentialsProvider;
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.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class LowLevelMultipartUpload {

    public static void main(String[] args) throws IOException {
        Regions clientRegion = Regions.DEFAULT_REGION;
        String bucketName = "*** Bucket name ***";
        String keyName = "*** Key name ***";
        String filePath = "*** Path to file to upload ***";

        File file = new File(filePath);
        long contentLength = file.length();
        long partSize = 5 * 1024 * 1024; // Set part size to 5 MB.

        try {
            AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
                    .withRegion(clientRegion)
                    .withCredentials(new ProfileCredentialsProvider())
                    .build();

            // Create a list of ETag objects. You retrieve ETags for each object part
            // uploaded,
            // then, after each individual part has been uploaded, pass the list of ETags to
            // the request to complete the upload.
            List<PartETag> partETags = new ArrayList<PartETag>();

            // Initiate the multipart upload.
            InitiateMultipartUploadRequest initRequest = new InitiateMultipartUploadRequest(bucketName, keyName);
            InitiateMultipartUploadResult initResponse = s3Client.initiateMultipartUpload(initRequest);

            // Upload the file parts.
            long filePosition = 0;
            for (int i = 1; filePosition < contentLength; i++) {
                // Because the last part could be less than 5 MB, adjust the part size as
                // needed.
                partSize = Math.min(partSize, (contentLength - filePosition));

                // Create the request to upload a part.
                UploadPartRequest uploadRequest = new UploadPartRequest()
                        .withBucketName(bucketName)
                        .withKey(keyName)
                        .withUploadId(initResponse.getUploadId())
                        .withPartNumber(i)
                        .withFileOffset(filePosition)
                        .withFile(file)
                        .withPartSize(partSize);

                // Upload the part and add the response's ETag to our list.
                UploadPartResult uploadResult = s3Client.uploadPart(uploadRequest);
                partETags.add(uploadResult.getPartETag());

                filePosition += partSize;
            }

            // Complete the multipart upload.
            CompleteMultipartUploadRequest compRequest = new CompleteMultipartUploadRequest(bucketName, keyName,
                    initResponse.getUploadId(), partETags);
            s3Client.completeMultipartUpload(compRequest);
        } catch (AmazonServiceException e) {
            // The call was transmitted successfully, but Amazon S3 couldn't process
            // it, so it returned an error response.
            e.printStackTrace();
        } catch (SdkClientException e) {
            // Amazon S3 couldn't be contacted for a response, or the client
            // couldn't parse the response from Amazon S3.
            e.printStackTrace();
        }
    }
}
```

------
#### [ .NET ]

以下 C\$1 示例演示如何使用低级别 适用于 .NET 的 SDK 分段上传 API 将文件上传到 S3 存储桶。有关 Amazon S3 分段上传的信息，请参阅 [在 Amazon S3 中使用分段上传来上传和复制对象](mpuoverview.md)。

**注意**  
如果使用 适用于 .NET 的 SDK API 上传大型对象，数据写入到请求流时可能出现超时。您可以使用 `UploadPartRequest` 设置显式超时。

以下 C\$1 示例使用低级别分段上传 API 将文件上传到 S3 存储桶。有关设置和运行代码示例的信息，请参阅《适用于 .NET 的 AWS SDK 开发人员指南》**中的[适用于 .NET 的 AWS SDK 入门](https://docs.aws.amazon.com/sdk-for-net/latest/developer-guide/net-dg-setup.html)。

```
using Amazon;
using Amazon.Runtime;
using Amazon.S3;
using Amazon.S3.Model;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;

namespace Amazon.DocSamples.S3
{
    class UploadFileMPULowLevelAPITest
    {
        private const string bucketName = "*** provide bucket name ***";
        private const string keyName = "*** provide a name for the uploaded object ***";
        private const string filePath = "*** provide the full path name of the file to upload ***";
        // Specify your bucket region (an example region is shown).
        private static readonly RegionEndpoint bucketRegion = RegionEndpoint.USWest2;
        private static IAmazonS3 s3Client;

        public static void Main()
        {
            s3Client = new AmazonS3Client(bucketRegion);
            Console.WriteLine("Uploading an object");
            UploadObjectAsync().Wait(); 
        }

        private static async Task UploadObjectAsync()
        {
            // Create list to store upload part responses.
            List<UploadPartResponse> uploadResponses = new List<UploadPartResponse>();

            // Setup information required to initiate the multipart upload.
            InitiateMultipartUploadRequest initiateRequest = new InitiateMultipartUploadRequest
            {
                BucketName = bucketName,
                Key = keyName
            };

            // Initiate the upload.
            InitiateMultipartUploadResponse initResponse =
                await s3Client.InitiateMultipartUploadAsync(initiateRequest);

            // Upload parts.
            long contentLength = new FileInfo(filePath).Length;
            long partSize = 5 * (long)Math.Pow(2, 20); // 5 MB

            try
            {
                Console.WriteLine("Uploading parts");
        
                long filePosition = 0;
                for (int i = 1; filePosition < contentLength; i++)
                {
                    UploadPartRequest uploadRequest = new UploadPartRequest
                        {
                            BucketName = bucketName,
                            Key = keyName,
                            UploadId = initResponse.UploadId,
                            PartNumber = i,
                            PartSize = partSize,
                            FilePosition = filePosition,
                            FilePath = filePath
                        };

                    // Track upload progress.
                    uploadRequest.StreamTransferProgress +=
                        new EventHandler<StreamTransferProgressArgs>(UploadPartProgressEventCallback);

                    // Upload a part and add the response to our list.
                    uploadResponses.Add(await s3Client.UploadPartAsync(uploadRequest));

                    filePosition += partSize;
                }

                // Setup to complete the upload.
                CompleteMultipartUploadRequest completeRequest = new CompleteMultipartUploadRequest
                    {
                        BucketName = bucketName,
                        Key = keyName,
                        UploadId = initResponse.UploadId
                     };
                completeRequest.AddPartETags(uploadResponses);

                // Complete the upload.
                CompleteMultipartUploadResponse completeUploadResponse =
                    await s3Client.CompleteMultipartUploadAsync(completeRequest);
            }
            catch (Exception exception)
            {
                Console.WriteLine("An AmazonS3Exception was thrown: { 0}", exception.Message);

                // Abort the upload.
                AbortMultipartUploadRequest abortMPURequest = new AbortMultipartUploadRequest
                {
                    BucketName = bucketName,
                    Key = keyName,
                    UploadId = initResponse.UploadId
                };
               await s3Client.AbortMultipartUploadAsync(abortMPURequest);
            }
        }
        public static void UploadPartProgressEventCallback(object sender, StreamTransferProgressArgs e)
        {
            // Process event. 
            Console.WriteLine("{0}/{1}", e.TransferredBytes, e.TotalBytes);
        }
    }
}
```

------
#### [ PHP ]

本主题说明如何使用 适用于 PHP 的 AWS SDK 版本 3 中的低级别 `uploadPart` 方法来以分段形式上传文件。有关适用于 Ruby 的 AWS 开发工具包 API 的更多信息，请转到[适用于 Ruby 的 AWS 开发工具包 – 版本 2](https://docs.aws.amazon.com/sdkforruby/api/index.html)。

以下 PHP 示例使用低级别 PHP API 分段上传将文件上传到 Amazon S3 存储桶。

```
 require 'vendor/autoload.php';

use Aws\S3\Exception\S3Exception;
use Aws\S3\S3Client;

$bucket = '*** Your Bucket Name ***';
$keyname = '*** Your Object Key ***';
$filename = '*** Path to and Name of the File to Upload ***';

$s3 = new S3Client([
    'version' => 'latest',
    'region'  => 'us-east-1'
]);

$result = $s3->createMultipartUpload([
    'Bucket'       => $bucket,
    'Key'          => $keyname,
    'StorageClass' => 'REDUCED_REDUNDANCY',
    'Metadata'     => [
        'param1' => 'value 1',
        'param2' => 'value 2',
        'param3' => 'value 3'
    ]
]);
$uploadId = $result['UploadId'];

// Upload the file in parts.
try {
    $file = fopen($filename, 'r');
    $partNumber = 1;
    while (!feof($file)) {
        $result = $s3->uploadPart([
            'Bucket'     => $bucket,
            'Key'        => $keyname,
            'UploadId'   => $uploadId,
            'PartNumber' => $partNumber,
            'Body'       => fread($file, 5 * 1024 * 1024),
        ]);
        $parts['Parts'][$partNumber] = [
            'PartNumber' => $partNumber,
            'ETag' => $result['ETag'],
        ];
        $partNumber++;

        echo "Uploading part $partNumber of $filename." . PHP_EOL;
    }
    fclose($file);
} catch (S3Exception $e) {
    $result = $s3->abortMultipartUpload([
        'Bucket'   => $bucket,
        'Key'      => $keyname,
        'UploadId' => $uploadId
    ]);

    echo "Upload of $filename failed." . PHP_EOL;
}

// Complete the multipart upload.
$result = $s3->completeMultipartUpload([
    'Bucket'   => $bucket,
    'Key'      => $keyname,
    'UploadId' => $uploadId,
    'MultipartUpload'    => $parts,
]);
$url = $result['Location'];

echo "Uploaded $filename to $url." . PHP_EOL;
```

------

## 使用 适用于 Ruby 的 AWS SDK
<a name="mpuoverview-ruby-sdk"></a>

适用于 Ruby 的 AWS SDK 版本 3 支持两种 Amazon S3 分段上传方式。对于第一个选项，您可以使用托管文件上传。有关更多信息，请参阅 *AWS 开发人员博客*中的[将文件上传至 Amazon S3](https://aws.amazon.com/blogs/developer/uploading-files-to-amazon-s3/)。托管文件上传是建议用于将文件上传到存储桶的方法。它们提供以下优势：
+ 管理大于 15MB 的对象的分段上传。
+ 正确打开二进制模式的文件，规避编码问题。
+ 在并行上传较大对象的多个部分时，使用多个线程。

此外，您还可以直接使用以下分段上传客户端操作：
+ [create\$1multipart\$1upload](https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Client.html#create_multipart_upload-instance_method) – 启动分段上传，并返回上传 ID。
+ [upload\$1part](https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Client.html#upload_part-instance_method) – 上传分段上传中的一部分。
+ [upload\$1part\$1copy](https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Client.html#upload_part_copy-instance_method) – 将现有对象作为数据源，并复制其中的数据，上传一部分。
+ [complete\$1multipart\$1upload](https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Client.html#complete_multipart_upload-instance_method) – 整合先前上传的部分，完成分段上传。
+ [abort\$1multipart\$1upload](https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Client.html#abort_multipart_upload-instance_method) – 停止分段上传。

# 使用高级别 .NET TransferUtility 类上传目录。
<a name="HLuploadDirDotNet"></a>

您可以使用 `TransferUtility` 类上传整个目录。默认情况下，该 API 仅上传位于指定目录的根目录中的文件。但是，您可以指定以递归方式上传所有子目录中的文件。

要根据筛选条件选择指定目录中的文件，请指定筛选表达式。例如，要从目录中仅上传 `PDF` 文件，请指定 `"*.pdf"` 筛选表达式。

在从目录中上传文件时，您不必为生成的对象指定键名。Amazon S3 会使用原始文件路径构造键名。例如，假设您有一个名为 `c:\myfolder` 的目录，并且此目录具有以下结构：

**Example**  

```
1. C:\myfolder
2.       \a.txt
3.       \b.pdf
4.       \media\               
5.              An.mp3
```

上传此目录时，Amazon S3 将使用以下密钥名称：

**Example**  

```
1. a.txt
2. b.pdf
3. media/An.mp3
```

**Example**  
以下 C\$1 代码示例将一个目录上传到 Amazon S3 存储桶。它说明如何使用各种 `TransferUtility.UploadDirectory` 重载来上传目录。每个对上传的后续调用都将替换先前的上传。有关设置和运行代码示例的信息，请参阅《适用于 .NET 的 AWS SDK 开发人员指南》**中的[适用于 .NET 的 AWS SDK 入门](https://docs.aws.amazon.com/sdk-for-net/latest/developer-guide/net-dg-setup.html)。  

```
using Amazon;
using Amazon.S3;
using Amazon.S3.Transfer;
using System;
using System.IO;
using System.Threading.Tasks;

namespace Amazon.DocSamples.S3
{
    class UploadDirMPUHighLevelAPITest
    {
        private const string existingBucketName = "*** bucket name ***";
        private const string directoryPath = @"*** directory path ***";
        // The example uploads only .txt files.
        private const string wildCard = "*.txt";
        // Specify your bucket region (an example region is shown).
        private static readonly RegionEndpoint bucketRegion = RegionEndpoint.USWest2;
        private static IAmazonS3 s3Client;
        static void Main()
        {
            s3Client = new AmazonS3Client(bucketRegion);
            UploadDirAsync().Wait();
        }

        private static async Task UploadDirAsync()
        {
            try
            {
                var directoryTransferUtility =
                    new TransferUtility(s3Client);

                // 1. Upload a directory.
                await directoryTransferUtility.UploadDirectoryAsync(directoryPath,
                    existingBucketName);
                Console.WriteLine("Upload statement 1 completed");

                // 2. Upload only the .txt files from a directory 
                //    and search recursively. 
                await directoryTransferUtility.UploadDirectoryAsync(
                                               directoryPath,
                                               existingBucketName,
                                               wildCard,
                                               SearchOption.AllDirectories);
                Console.WriteLine("Upload statement 2 completed");

                // 3. The same as Step 2 and some optional configuration. 
                //    Search recursively for .txt files to upload.
                var request = new TransferUtilityUploadDirectoryRequest
                {
                    BucketName = existingBucketName,
                    Directory = directoryPath,
                    SearchOption = SearchOption.AllDirectories,
                    SearchPattern = wildCard
                };

                await directoryTransferUtility.UploadDirectoryAsync(request);
                Console.WriteLine("Upload statement 3 completed");
            }
            catch (AmazonS3Exception e)
            {
                Console.WriteLine(
                        "Error encountered ***. Message:'{0}' when writing an object", e.Message);
            }
            catch (Exception e)
            {
                Console.WriteLine(
                    "Unknown encountered on server. Message:'{0}' when writing an object", e.Message);
            }
        }
    }
}
```

# 列出分段上传
<a name="list-mpu"></a>

可以使用 AWS CLI、REST API 或 AWS SDK 检索 Amazon S3 中正在进行的分段上传的列表。您可以使用分段上传以编程方式将单个对象上传到 Amazon S3。分段上传通过一次移动对象数据的一部分，将对象移动到 Amazon S3 中。有关分段上传的更多一般信息，请参阅[在 Amazon S3 中使用分段上传来上传和复制对象](mpuoverview.md)。

有关使用分段上传以及额外的校验和来上传对象的端到端过程，请参阅[教程：通过分段上传来上传对象并验证其数据完整性](tutorial-s3-mpu-additional-checksums.md)。

下一节介绍如何使用 AWS Command Line Interface、Amazon S3 REST API 和 AWS SDK 列出正在进行的分段上传。

## 使用 AWS CLI 列出分段上传
<a name="list-mpu-cli"></a>

AWS Command Line Interface 中的以下各部分介绍了适用于列出分段上传的操作。
+ [list-parts](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3api/list-parts.html)‐ 列出特定分段上传的已上传部分。
+ [list-multipart-uploads](https://docs.aws.amazon.com/cli/latest/reference/s3api/list-multipart-uploads.html)‐ 列出正在进行的分段上传。

# 使用 REST API 列出分段上传
<a name="list-mpu-rest"></a>

*Amazon Simple Storage Service API 参考*的下面几节描述了列出分段上传的 REST API：
+ [ListParts](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListParts.html)‐ 列出特定分段上传的已上传部分。
+ [ListMultipartUploads](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListMultipartUploads.html)‐ 列出正在进行的分段上传。

## 使用 AWS SDK（低级别 API）列出分段上传
<a name="list-aws-sdk"></a>

------
#### [ Java ]

要使用适用于 Java 的 AWS SDK 列出存储桶上所有正在进行的分段上传，可以使用低级别 API 类来执行以下操作：


**低级别 API 分段上传列表过程**  

|  |  | 
| --- |--- |
| 1 | 创建 `ListMultipartUploadsRequest` 类的实例并提供存储桶名称。 | 
| 2 | 运行 S3Client `listMultipartUploads` 方法。该方法将返回 `ListMultipartUploadsResponse` 类的实例，以向您提供有关正在进行的分段上传的信息。 | 

有关如何使用适用于 Java 的 AWS SDK 列出分段上传的示例，请参阅《Amazon S3 API Reference》**中的 [List multipart uploads](https://docs.aws.amazon.com/AmazonS3/latest/API/s3_example_s3_ListMultipartUploads_section.html)。

------
#### [ .NET ]

要列出特定存储桶上所有正在进行的分段上传，请使用 适用于 .NET 的 SDK 低级别分段上传 API 的 `ListMultipartUploadsRequest` 类。`AmazonS3Client.ListMultipartUploads` 方法将返回 `ListMultipartUploadsResponse` 类（提供有关正在进行的分段上传的信息）的实例。

正在进行的分段上传是使用启动分段上传请求启动但尚未完成或停止的分段上传。有关 Amazon S3 分段上传的更多信息，请参阅 [在 Amazon S3 中使用分段上传来上传和复制对象](mpuoverview.md)。

以下 C\$1 示例演示如何使用 适用于 .NET 的 SDK 列出存储桶上所有正在进行的分段上传。有关设置和运行代码示例的信息，请参阅《适用于 .NET 的 AWS SDK 开发人员指南》**中的[适用于 .NET 的 AWS SDK 入门](https://docs.aws.amazon.com/sdk-for-net/latest/developer-guide/net-dg-setup.html)。

```
ListMultipartUploadsRequest request = new ListMultipartUploadsRequest
{
	 BucketName = bucketName // Bucket receiving the uploads.
};

ListMultipartUploadsResponse response = await AmazonS3Client.ListMultipartUploadsAsync(request);
```

------
#### [ PHP ]

本主题说明如何使用版本 3 的 适用于 PHP 的 AWS SDK 中的低级别 API 类列出存储桶上所有正在进行的分段上传。有关适用于 Ruby 的 AWS 开发工具包 API 的更多信息，请转到[适用于 Ruby 的 AWS 开发工具包 – 版本 2](https://docs.aws.amazon.com/sdkforruby/api/index.html)。

以下 PHP 示例演示如何列出存储桶上所有正在进行的分段上传。

```
 require 'vendor/autoload.php';

use Aws\S3\S3Client;

$bucket = '*** Your Bucket Name ***';

$s3 = new S3Client([
    'version' => 'latest',
    'region'  => 'us-east-1'
]);

// Retrieve a list of the current multipart uploads.
$result = $s3->listMultipartUploads([
    'Bucket' => $bucket
]);

// Write the list of uploads to the page.
print_r($result->toArray());
```

------

# 使用 AWS SDK 跟踪分段上传
<a name="track-mpu"></a>

可以使用侦听接口跟踪对象上传到 Amazon S3 的进度。高级别分段上传 API 提供了这样的侦听接口，名为 `ProgressListener`。进度事件将定期发生，并且会通知侦听者已传输的字节。有关分段上传的更多一般信息，请参阅[在 Amazon S3 中使用分段上传来上传和复制对象](mpuoverview.md)。

有关使用分段上传以及额外的校验和来上传对象的端到端过程，请参阅[教程：通过分段上传来上传对象并验证其数据完整性](tutorial-s3-mpu-additional-checksums.md)。

下一节介绍如何通过 AWS SDK 跟踪分段上传。

------
#### [ Java ]

**Example**  
以下 Java 代码将上传文件并使用 `ExecutionInterceptor` 来跟踪上传进度。有关如何创建和测试有效示例的说明，请参阅《适用于 Java 的 AWS SDK 2.x Developer Guide》中的 [Getting Started](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html)。  

```
import java.nio.file.Paths;

import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider;
import software.amazon.awssdk.core.async.AsyncRequestBody;
import software.amazon.awssdk.core.interceptor.Context;
import software.amazon.awssdk.core.interceptor.ExecutionAttributes;
import software.amazon.awssdk.core.interceptor.ExecutionInterceptor;
import software.amazon.awssdk.services.s3.S3AsyncClient;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;

public class TrackMPUProgressUsingHighLevelAPI {

    static class ProgressListener implements ExecutionInterceptor {
        private long transferredBytes = 0;

        @Override
        public void beforeTransmission(Context.BeforeTransmission context, ExecutionAttributes executionAttributes) {
            if (context.httpRequest().firstMatchingHeader("Content-Length").isPresent()) {
                String contentLength = context.httpRequest().firstMatchingHeader("Content-Length").get();
                long partSize = Long.parseLong(contentLength);
                transferredBytes += partSize;
                System.out.println("Transferred bytes: " + transferredBytes);
            }
        }
    }

    public static void main(String[] args) throws Exception {
        String existingBucketName = "*** Provide bucket name ***";
        String keyName = "*** Provide object key ***";
        String filePath = "*** file to upload ***";

        S3AsyncClient s3Client = S3AsyncClient.builder()
                .credentialsProvider(ProfileCredentialsProvider.create())
                .overrideConfiguration(c -> c.addExecutionInterceptor(new ProgressListener()))
                .build();

        // For more advanced uploads, you can create a request object
        // and supply additional request parameters (ex: progress listeners,
        // canned ACLs, etc.)
        PutObjectRequest request = PutObjectRequest.builder()
                .bucket(existingBucketName)
                .key(keyName)
                .build();

        AsyncRequestBody requestBody = AsyncRequestBody.fromFile(Paths.get(filePath));

        // You can ask the upload for its progress, or you can
        // add a ProgressListener to your request to receive notifications
        // when bytes are transferred.
        // S3AsyncClient processes all transfers asynchronously,
        // so this call will return immediately.
        var upload = s3Client.putObject(request, requestBody);

        try {
            // You can block and wait for the upload to finish
            upload.join();
        } catch (Exception exception) {
            System.out.println("Unable to upload file, upload aborted.");
            exception.printStackTrace();
        } finally {
            s3Client.close();
        }
    }
}
```

------
#### [ .NET ]

以下 C\$1 示例使用 `TransferUtility` 类将文件上传到 S3 存储桶并跟踪上传的进度。有关设置和运行代码示例的信息，请参阅《适用于 .NET 的 AWS SDK 开发人员指南》**中的[适用于 .NET 的 AWS SDK 入门](https://docs.aws.amazon.com/sdk-for-net/latest/developer-guide/net-dg-setup.html)。

```
using Amazon;
using Amazon.S3;
using Amazon.S3.Transfer;
using System;
using System.Threading.Tasks;

namespace Amazon.DocSamples.S3
{
    class TrackMPUUsingHighLevelAPITest
    {
        private const string bucketName = "*** provide the bucket name ***";
        private const string keyName = "*** provide the name for the uploaded object ***";
        private const string filePath = " *** provide the full path name of the file to upload **";
        // Specify your bucket region (an example region is shown).
        private static readonly RegionEndpoint bucketRegion = RegionEndpoint.USWest2;
        private static IAmazonS3 s3Client;


        public static void Main()
        {
            s3Client = new AmazonS3Client(bucketRegion);
            TrackMPUAsync().Wait();
        }

        private static async Task TrackMPUAsync()
        {
            try
            {
                var fileTransferUtility = new TransferUtility(s3Client);

                // Use TransferUtilityUploadRequest to configure options.
                // In this example we subscribe to an event.
                var uploadRequest =
                    new TransferUtilityUploadRequest
                    {
                        BucketName = bucketName,
                        FilePath = filePath,
                        Key = keyName
                    };

                uploadRequest.UploadProgressEvent +=
                    new EventHandler<UploadProgressArgs>
                        (uploadRequest_UploadPartProgressEvent);

                await fileTransferUtility.UploadAsync(uploadRequest);
                Console.WriteLine("Upload completed");
            }
            catch (AmazonS3Exception e)
            {
                Console.WriteLine("Error encountered on server. Message:'{0}' when writing an object", e.Message);
            }
            catch (Exception e)
            {
                Console.WriteLine("Unknown encountered on server. Message:'{0}' when writing an object", e.Message);
            }
        }

        static void uploadRequest_UploadPartProgressEvent(object sender, UploadProgressArgs e)
        {
            // Process event.
            Console.WriteLine("{0}/{1}", e.TransferredBytes, e.TotalBytes);
        }
    }
}
```

------

# 中止分段上传
<a name="abort-mpu"></a>

启动分段上传后，您便开始上传段。Amazon S3 存储这些分段，并且仅当您上传了所有分段并发送请求来完成分段上传后，才创建对象。在收到完成分段上传请求后，Amazon S3 会将这些段汇集在一起并创建一个对象。如果您未成功发送完成分段上传请求，S3 不会汇集这些分段，并且不会创建任何对象。如果您不希望在上传各分段后完成分段上传，则应中止分段上传。

您需要为与上传的分段关联的所有存储付费。建议务必完成分段上传，或者停止分段上传来移除任何已上传的分段。有关定价的更多信息，请参阅[分段上传和定价](mpuoverview.md#mpuploadpricing)。

您还可以使用存储桶生命周期配置停止未完成的分段上传。有关更多信息，请参阅 [配置存储桶生命周期配置以删除未完成的分段上传](mpu-abort-incomplete-mpu-lifecycle-config.md)。

下一节介绍如何使用 AWS Command Line Interface、REST API 或 AWS SDK 来停止 Amazon S3 中正在进行的分段上传。

## 使用 AWS CLI
<a name="abort-mpu-cli"></a>

有关使用 AWS CLI 停止分段上传的更多信息，请参阅《AWS CLI 命令参考》**中的 [abort-multipart-upload](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3api/abort-multipart-upload.html)。

## 使用 REST API
<a name="abort-mpu-rest"></a>

有关使用 REST API 停止分段上传的更多信息，请参阅 *Amazon Simple Storage Service API 参考*中的 [AbortMultipartUpload](https://docs.aws.amazon.com/AmazonS3/latest/API/API_AbortMultipartUpload.html)。

## 使用 AWS SDK（高级别 API）
<a name="abort-mpu-high-level"></a>

------
#### [ Java ]

要使用适用于 Java 的 AWS SDK 停止正在进行的分段上传，可以中止在指定的日期之前启动但仍在进行的上传。启动上传后，上传将被视为正在进行，直到您完成或停止该操作。

要停止分段上传，您可以：


|  |  | 
| --- |--- |
| 1 | 创建 S3Client 实例。 | 
| 2 | 通过传递存储桶名称和其它必需的参数，使用客户端的中止方法。 | 

**注意**  
您也可以停止特定的分段上传。有关更多信息，请参阅 [使用 AWS SDK（低级别 API）](#abort-mpu-low-level)。

有关如何使用适用于 Java 的 AWS SDK 中止分段上传的示例，请参阅《Amazon S3 API Reference》**中的 [Cancel a multipart upload](https://docs.aws.amazon.com/AmazonS3/latest/API/s3_example_s3_AbortMultipartUpload_section.html)。

------
#### [ .NET ]

以下 C\$1 示例将停止一周前在特定存储桶上启动的正在进行的所有分段上传。有关设置和运行代码示例的信息，请参阅《适用于 .NET 的 AWS SDK 开发人员指南》**中的[适用于 .NET 的 AWS SDK 入门](https://docs.aws.amazon.com/sdk-for-net/latest/developer-guide/net-dg-setup.html)。

```
using Amazon;
using Amazon.S3;
using Amazon.S3.Transfer;
using System;
using System.Threading.Tasks;

namespace Amazon.DocSamples.S3
{
    class AbortMPUUsingHighLevelAPITest
    {
        private const string bucketName = "*** provide bucket name ***";
        // Specify your bucket region (an example region is shown).
        private static readonly RegionEndpoint bucketRegion = RegionEndpoint.USWest2;
        private static IAmazonS3 s3Client;

        public static void Main()
        {
            s3Client = new AmazonS3Client(bucketRegion);
            AbortMPUAsync().Wait();
        }

        private static async Task AbortMPUAsync()
        {
            try
            {
                var transferUtility = new TransferUtility(s3Client);

                // Abort all in-progress uploads initiated before the specified date.
                await transferUtility.AbortMultipartUploadsAsync(
                    bucketName, DateTime.Now.AddDays(-7));
            }
            catch (AmazonS3Exception e)
            {
                Console.WriteLine("Error encountered on server. Message:'{0}' when writing an object", e.Message);
            }
            catch (Exception e)
            {
                Console.WriteLine("Unknown encountered on server. Message:'{0}' when writing an object", e.Message);
            }
        } 
    }
}
```

**注意**  
您也可以停止特定的分段上传。有关更多信息，请参阅 [使用 AWS SDK（低级别 API）](#abort-mpu-low-level)。

------

## 使用 AWS SDK（低级别 API）
<a name="abort-mpu-low-level"></a>

您可以通过调用 `AmazonS3.abortMultipartUpload` 方法停止正在进行的分段上传。此方法将删除任何已上传到 Amazon S3 的分段并释放资源。您必须提供上传 ID、存储桶名称和键名称。以下 Java 代码示例演示如何停止正在进行的分段上传。

要停止分段上传，请提供上传时使用的上传 ID、存储桶名称和键名。停止一个分段上传之后，您便无法使用相应的上传 ID 上传其他分段。有关 Amazon S3 分段上传的更多信息，请参阅 [在 Amazon S3 中使用分段上传来上传和复制对象](mpuoverview.md)。

------
#### [ Java ]

要使用适用于 Java 的 AWS SDK 停止正在进行的特定分段上传，可以使用低级别 API 通过提供存储桶名称、对象键和上传 ID 来中止上传。

**注意**  
可以停止所有在特定时间之前启动但仍在进行的分段上传，而不是中止某个特定的分段上传。此清理操作对于停止您已启动但未完成或停止的旧分段上传非常有用。有关更多信息，请参阅 [使用 AWS SDK（高级别 API）](#abort-mpu-high-level)。

有关如何使用适用于 Java 的 AWS SDK 中止特定分段上传的示例，请参阅《Amazon S3 API Reference》**中的 [Cancel a multipart upload](https://docs.aws.amazon.com/AmazonS3/latest/API/s3_example_s3_AbortMultipartUpload_section.html)。

------
#### [ .NET ]

以下 C\$1 示例演示如何停止分段上传。有关包含以下代码的完整 C\$1 示例，请参阅 [使用 AWS SDK（低级别 API）](mpu-upload-object.md#mpu-upload-low-level)。

```
AbortMultipartUploadRequest abortMPURequest = new AbortMultipartUploadRequest
{
    BucketName = existingBucketName,
    Key = keyName,
    UploadId = initResponse.UploadId
};
await AmazonS3Client.AbortMultipartUploadAsync(abortMPURequest);
```

还可以中止在特定时间之前启动的所有正在进行的分段上传。对于中止未完成或已中止的分段上传，此清理操作很有用。有关更多信息，请参阅 [使用 AWS SDK（高级别 API）](#abort-mpu-high-level)。

------
#### [ PHP ]

本示例介绍如何使用 适用于 PHP 的 AWS SDK 的版本 3 中的类中止正在进行的分段上传。有关适用于 Ruby 的 AWS 开发工具包 API 的更多信息，请转到[适用于 Ruby 的 AWS 开发工具包 – 版本 2](https://docs.aws.amazon.com/sdkforruby/api/index.html)。例如，`abortMultipartUpload()` 方法。

有关适用于 Ruby 的 AWS 开发工具包 API 的更多信息，请转到[适用于 Ruby 的 AWS 开发工具包 – 版本 2](https://docs.aws.amazon.com/sdkforruby/api/index.html)。

```
 require 'vendor/autoload.php';

use Aws\S3\S3Client;

$bucket = '*** Your Bucket Name ***';
$keyname = '*** Your Object Key ***';
$uploadId = '*** Upload ID of upload to Abort ***';

$s3 = new S3Client([
    'version' => 'latest',
    'region'  => 'us-east-1'
]);

// Abort the multipart upload.
$s3->abortMultipartUpload([
    'Bucket'   => $bucket,
    'Key'      => $keyname,
    'UploadId' => $uploadId,
]);
```

------

# 使用分段上传复制对象
<a name="CopyingObjectsMPUapi"></a>

分段上传支持您将对象作为一组分段进行上传。本节中的示例将向您展示如何使用分段上传 API 复制大于 5 GB 的对象。有关分段上传的信息，请参阅[在 Amazon S3 中使用分段上传来上传和复制对象](mpuoverview.md)。

可以在单个操作中复制小于 5 GB 的对象，而无需使用分段上传 API。可以使用 AWS 管理控制台、AWS CLI、REST API 或 AWS SDK 复制小于 5 GB 的对象。有关更多信息，请参阅 [复制、移动和重命名对象](copy-object.md)。

有关使用分段上传以及额外的校验和来上传对象的端到端过程，请参阅[教程：通过分段上传来上传对象并验证其数据完整性](tutorial-s3-mpu-additional-checksums.md)。

下一节介绍如何使用 REST API 或 AWS SDK 通过分段上传来复制对象。

## 使用 REST API
<a name="CopyingObjctsUsingRESTMPUapi"></a>

*Amazon Simple Storage Service API 参考*的下面几节描述了适用于分段上传的 REST API。使用上传分段（复制）API 复制现有的对象，并通过在请求中添加 `x-amz-copy-source` 请求标头指定源对象。
+ [开始分段上传](https://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadInitiate.html)
+ [上传分段](https://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadUploadPart.html)
+ [上传分段（复制）](https://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadUploadPartCopy.html)
+ [完成分段上传](https://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadComplete.html)
+ [中止分段上传](https://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadAbort.html)
+ [列出分段](https://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadListParts.html)
+ [列出分段上传](https://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadListMPUpload.html)

您可以使用这些 API 生成您自己的 REST 请求，也可以使用我们提供的 SDK 之一。有关通过 AWS CLI 执行分段上传的更多信息，请参阅 [使用 AWS CLI](mpu-upload-object.md#UsingCLImpUpload)。有关开发工具包的更多信息，请参阅 [AWS SDK 对于分段上传的支持](mpuoverview.md#sdksupportformpu)。

## 使用 AWS 开发工具包
<a name="copy-object-mpu-sdks"></a>

要使用低级别 API 复制对象，请执行以下操作：
+ 通过调用 `AmazonS3Client.initiateMultipartUpload()` 方法启动分段上传。
+ 从 `AmazonS3Client.initiateMultipartUpload()` 方法返回的响应对象保存上传 ID。您为每个分段上传操作提供此上传 ID。
+ 复制所有段。对于需要复制的每个段，创建一个 `CopyPartRequest` 类的新实例。提供段信息，包括源和目标存储桶名称、源和目标对象键、上传 ID、段的第一个字节和最后一个字节的位置以及段编号。
+ 保存 `AmazonS3Client.copyPart()` 方法调用的响应。每个响应均包括 `ETag` 值和已上传分段的段编号。您需要此信息才能完成分段上传。
+ 调用 `AmazonS3Client.completeMultipartUpload()` 方法以完成复制操作。

------
#### [ Java ]

有关如何使用适用于 Java 的 AWS SDK 通过分段上传来复制对象的示例，请参阅《Amazon S3 API Reference》**中的 [Copy part of an object from another object](https://docs.aws.amazon.com/AmazonS3/latest/API/s3_example_s3_UploadPartCopy_section.html)。

------
#### [ .NET ]

以下 C\$1 示例说明如何使用 适用于 .NET 的 SDK 将大于 5 GB 的 Amazon S3 对象从一个源位置复制到另一个源位置，例如从一个存储桶复制到另一个存储桶。要复制小于 5 GB 的对象，请使用 [使用 AWS SDK](copy-object.md#CopyingObjectsUsingSDKs) 中所述的单个操作复制过程。有关 Amazon S3 分段上传的更多信息，请参阅[在 Amazon S3 中使用分段上传来上传和复制对象](mpuoverview.md)。

此示例说明如何使用 适用于 .NET 的 SDK 分段上传 API 将大于 5 GB 的 Amazon S3 对象从一个 S3 存储桶复制到另一个存储桶。

```
using Amazon;
using Amazon.S3;
using Amazon.S3.Model;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace Amazon.DocSamples.S3
{
    class CopyObjectUsingMPUapiTest
    {
        private const string sourceBucket = "*** provide the name of the bucket with source object ***";
        private const string targetBucket = "*** provide the name of the bucket to copy the object to ***";
        private const string sourceObjectKey = "*** provide the name of object to copy ***";
        private const string targetObjectKey = "*** provide the name of the object copy ***";
        // Specify your bucket region (an example region is shown).
        private static readonly RegionEndpoint bucketRegion = RegionEndpoint.USWest2; 
        private static IAmazonS3 s3Client;

        public static void Main()
        {
            s3Client = new AmazonS3Client(bucketRegion);
            Console.WriteLine("Copying an object");
            MPUCopyObjectAsync().Wait();
        }
        private static async Task MPUCopyObjectAsync()
        {
            // Create a list to store the upload part responses.
            List<UploadPartResponse> uploadResponses = new List<UploadPartResponse>();
            List<CopyPartResponse> copyResponses = new List<CopyPartResponse>();

            // Setup information required to initiate the multipart upload.
            InitiateMultipartUploadRequest initiateRequest =
                new InitiateMultipartUploadRequest
                {
                    BucketName = targetBucket,
                    Key = targetObjectKey
                };

            // Initiate the upload.
            InitiateMultipartUploadResponse initResponse =
                await s3Client.InitiateMultipartUploadAsync(initiateRequest);

            // Save the upload ID.
            String uploadId = initResponse.UploadId;

            try
            {
                // Get the size of the object.
                GetObjectMetadataRequest metadataRequest = new GetObjectMetadataRequest
                {
                    BucketName = sourceBucket,
                    Key = sourceObjectKey
                };

                GetObjectMetadataResponse metadataResponse =
                    await s3Client.GetObjectMetadataAsync(metadataRequest);
                long objectSize = metadataResponse.ContentLength; // Length in bytes.

                // Copy the parts.
                long partSize = 5 * (long)Math.Pow(2, 20); // Part size is 5 MB.

                long bytePosition = 0;
                for (int i = 1; bytePosition < objectSize; i++)
                {
                    CopyPartRequest copyRequest = new CopyPartRequest
                    {
                        DestinationBucket = targetBucket,
                        DestinationKey = targetObjectKey,
                        SourceBucket = sourceBucket,
                        SourceKey = sourceObjectKey,
                        UploadId = uploadId,
                        FirstByte = bytePosition,
                        LastByte = bytePosition + partSize - 1 >= objectSize ? objectSize - 1 : bytePosition + partSize - 1,
                        PartNumber = i
                    };

                    copyResponses.Add(await s3Client.CopyPartAsync(copyRequest));

                    bytePosition += partSize;
                }

                // Set up to complete the copy.
                CompleteMultipartUploadRequest completeRequest =
                new CompleteMultipartUploadRequest
                {
                    BucketName = targetBucket,
                    Key = targetObjectKey,
                    UploadId = initResponse.UploadId
                };
                completeRequest.AddPartETags(copyResponses);

                // Complete the copy.
                CompleteMultipartUploadResponse completeUploadResponse = 
                    await s3Client.CompleteMultipartUploadAsync(completeRequest);
            }
            catch (AmazonS3Exception e)
            {
                Console.WriteLine("Error encountered on server. Message:'{0}' when writing an object", e.Message);
            }
            catch (Exception e)
            {
                Console.WriteLine("Unknown encountered on server. Message:'{0}' when writing an object", e.Message);
            }
        }
    }
}
```

------

# 教程：通过分段上传来上传对象并验证其数据完整性
<a name="tutorial-s3-mpu-additional-checksums"></a>

 分段上传允许将单个对象作为一组分段上传。每个分段都是对象数据的连续部分。您可以独立上传以及按任意顺序上传这些对象分段。如果任意分段传输失败，可以重新传输该分段且不会影响其他分段。上传完所有的对象分段后，Amazon S3 将汇集这些分段并创建对象。一般而言，如果您的对象大小达到了 100 MB，您应该考虑使用分段上传，而不是在单个操作中上传对象。有关分段上传的更多信息，请参阅 [在 Amazon S3 中使用分段上传来上传和复制对象](mpuoverview.md)。有关分段上传的相关限制，请参阅 [Amazon S3 分段上传限制](qfacts.md)。

 可以使用校验和来验证资产在复制时是否未被更改。执行校验和包括使用算法按顺序迭代文件中的每个字节。Amazon S3 提供了多个校验和选项，用于检查数据的完整性。我们建议您将这些完整性检查作为持久性最佳实践加以执行，并确认每个字节在传输过程中都未经更改。Amazon S3 还支持以下算法：SHA-1、SHA-256、CRC32 和 CRC32C。Amazon S3 使用其中一个或多个算法来计算额外的校验和值，并将其存储为对象元数据的一部分。有关校验和的更多信息，请参阅[在 Amazon S3 中检查对象完整性](checking-object-integrity.md)。

**目标**  
 在本教程中，您将学习如何在 AWS 命令行界面（AWS CLI）中使用分段上传和额外的 SHA-256 校验和将对象上传到 Amazon S3。您还将学习如何通过计算已上传对象的 MD5 哈希值和 SHA-256 校验和，来检查对象的数据完整性。

**Topics**
+ [

## 先决条件
](#mpu-prerequisites)
+ [

## 步骤 1：创建大文件
](#create-large-file-step1)
+ [

## 步骤 2：将文件拆分为多个文件
](#split-large-file-step2)
+ [

## 步骤 3：创建分段上传并指定额外的校验和
](#create-multipart-upload-step3)
+ [

## 步骤 4：上传分段上传的分段
](#upload-parts-step4)
+ [

## 步骤 5：列出分段上传的所有分段
](#list-parts-step5)
+ [

## 步骤 6：完成分段上传
](#complete-multipart-upload-step6)
+ [

## 步骤 7：确认对象上传到存储桶
](#confirm-upload-step7)
+ [

## 步骤 8：使用 MD5 校验和验证对象完整性
](#verify-object-integrity-step8)
+ [

## 步骤 9：使用额外的校验和验证对象完整性
](#verify-object-integrity-sha256-step9)
+ [

## 步骤 10：清除资源
](#clean-up-step10)

## 先决条件
<a name="mpu-prerequisites"></a>
+ 在开始本教程之前，请确保您有权访问要上传到的 Amazon S3 存储桶。有关更多信息，请参阅 [创建通用存储桶](create-bucket-overview.md)。
+  您必须安装并配置了 AWS CLI。如果未安装 AWS CLI，请参阅《AWS Command Line Interface用户指南》**中的 [Install or update to the latest version of the AWS CLI](https://docs.aws.amazon.com//cli/latest/userguide/getting-started-install.html)。
+ 或者，您可以从控制台中使用 AWS CloudShell 运行 AWS CLI 命令。AWS CloudShell 是一个基于浏览器、预先经过身份验证的 Shell，您可以直接从 AWS 管理控制台中启动它。有关更多信息，请参阅《AWS CloudShell 用户指南》**中的 [What is CloudShell?](https://docs.aws.amazon.com//cloudshell/latest/userguide/welcome.html) 和 [Getting started with AWS CloudShell](https://docs.aws.amazon.com//cloudshell/latest/userguide/getting-started.html)。

## 步骤 1：创建大文件
<a name="create-large-file-step1"></a>

如果您已经准备好要上传的文件，则可以在本教程中使用该文件。否则，请使用以下步骤创建一个 15 MB 的文件。有关分段上传的相关限制，请参阅 [Amazon S3 分段上传限制](qfacts.md)。

**创建大文件**

根据您使用的操作系统，使用以下命令之一来创建文件。

**Linux 或 macOS**  
要创建 15 MB 的文件，请打开本地终端并运行以下命令：

```
dd if=/dev/urandom of=census-data.bin bs=1M count=15
```

此命令创建一个名为 `census-data.bin` 的文件，其中填充了随机字节，大小为 15 MB。

**Windows**  
要创建 15 MB 的文件，请打开本地终端并运行以下命令：

```
fsutil file createnew census-data.bin 15728640
```

此命令创建一个名为 `census-data.bin` 的文件，其中包含任意数据，大小为 15 MB（15728640 字节）。

## 步骤 2：将文件拆分为多个文件
<a name="split-large-file-step2"></a>

要执行分段上传，必须将大文件拆分为若干较小的分段。然后，可以使用分段上传过程来上传较小的分段。此步骤演示如何将[步骤 1](#create-large-file-step1) 中创建的大文件拆分为较小的分段。以下示例使用名为 `census-data.bin` 的 15 MB 文件。

**将大文件拆分为多个分段**

**Linux 或 macOS**  
要将大文件分成 5 MB 的分段，请使用 `split` 命令。打开终端并运行以下命令：

```
split -b 5M -d census-data.bin census-part
```

此命令将 `census-data.bin` 拆分成名为 `census-part**` 的 5 MB 分段，其中 `**` 是从 `00` 开始的数字后缀。

**Windows**  
要拆分大文件，请使用 PowerShell。打开 [Powershell](https://learn.microsoft.com/en-us/powershell/) 并运行以下命令：

```
$inputFile = "census-data.bin"
$outputFilePrefix = "census-part"
$chunkSize = 5MB

$fs = [System.IO.File]::OpenRead($inputFile)
$buffer = New-Object byte[] $chunkSize
$fileNumber = 0

while ($fs.Position -lt $fs.Length) {
$bytesRead = $fs.Read($buffer, 0, $chunkSize)
$outputFile = "{0}{1:D2}" -f $outputFilePrefix, $fileNumber
$fileStream = [System.IO.File]::Create($outputFile)
$fileStream.Write($buffer, 0, $bytesRead)
$fileStream.Close()
$fileNumber++
}

$fs.Close()
```

此 PowerShell 脚本以 5 MB 大小的分块读取大文件，并将每个分块写入一个带有数字后缀的新文件。

运行相应的命令后，您应该会在执行该命令的目录中看到各个分段。每个分段都有一个与其分段编号对应的后缀，例如：

```
census-part00 census-part01 census-part02
```

## 步骤 3：创建分段上传并指定额外的校验和
<a name="create-multipart-upload-step3"></a>

要开始分段上传过程，您需要创建分段上传请求。此步骤包括启动分段上传以及为数据完整性指定额外的校验和。以下示例使用 SHA-256 校验和。如果您想要提供描述正上传的对象的任何元数据，必须在请求中提供它以便开始分段上传。

**注意**  
在本步骤和后续步骤中，本教程使用 SHA-256 额外算法。您可以选择为这些步骤使用其他的额外校验和，例如 CRC32、CRC32C 或 SHA-1。如果使用不同的算法，则必须在整个教程步骤中都使用该算法。

**开始分段上传**

在终端中，使用以下 `create-multipart-upload` 命令开始存储桶的分段上传。将 `amzn-s3-demo-bucket1` 替换为实际存储桶名称。另外，请用您选择的文件名替换 `census_data_file`。上传完成后，此文件名将成为对象键。

```
aws s3api create-multipart-upload --bucket amzn-s3-demo-bucket1 --key 'census_data_file' --checksum-algorithm sha256
```

如果您的请求执行成功，您将看到如下 JSON 输出：

```
{
    "ServerSideEncryption": "AES256",
    "ChecksumAlgorithm": "SHA256",
    "Bucket": "amzn-s3-demo-bucket1",
    "Key": "census_data_file",
    "UploadId": "cNV6KCSNANFZapz1LUGPC5XwUVi1n6yUoIeSP138sNOKPeMhpKQRrbT9k0ePmgoOTCj9K83T4e2Gb5hQvNoNpCKqyb8m3.oyYgQNZD6FNJLBZluOIUyRE.qM5yhDTdhz"
}
```

**注意**  
当您发送请求以开始分段上传时，Amazon S3 将返回具有上传 ID 的响应，此 ID 是分段上传的唯一标识符。无论您何时上传分段、列出分段、完成上传或停止上传，您都必须包括此上传 ID。后续步骤需要用到 `UploadId`、`Key` 和 `Bucket` 值，因此请务必保存这些值。  
此外，如果您将分段上传与额外的校验和结合使用，则分段编号必须是连续的。如果您使用不连续的分段编号，则 `complete-multipart-upload` 请求可能会导致 HTTP `500 Internal Server Error`。

## 步骤 4：上传分段上传的分段
<a name="upload-parts-step4"></a>

在此步骤中，您将分段上传的各个分段上传到 S3 存储桶。使用 `upload-part` 命令单独上传每个分段。此过程要求为每个分段指定上传 ID、分段编号和要上传的文件。

**上传分段**

1. 上传分段时，除了上传 ID，还必须使用 `--part-number` 参数来指定分段编号。您可以选择 1 和 10000 之间的任意分段编号。分段编号在您正在上传的对象中唯一地识别分段及其位置。您选择的分段编号必须为连续序列（例如，它可以是 1、2 或 3）。如果您使用之前上传的分段的同一分段编号上传新分段，则之前上传的分段将被覆盖。

1. 使用 `upload-part` 命令来上传分段上传的每个分段。`--upload-id` 与[步骤 3](#create-multipart-upload-step3) 中 `create-multipart-upload` 命令创建的输出内容相同。要上传数据的第一个分段，请使用以下命令：

   ```
   aws s3api upload-part --bucket amzn-s3-demo-bucket1 --key 'census_data_file' --part-number 1 --body census-part00 --upload-id "cNV6KCSNANFZapz1LUGPC5XwUVi1n6yUoIeSP138sNOKPeMhpKQRrbT9k0ePmgoOTCj9K83T4e2Gb5hQvNoNpCKqyb8m3.oyYgQNZD6FNJLBZluOIUyRE.qM5yhDTdhz" --checksum-algorithm SHA256
   ```

   完成每个 `upload-part` 命令后，您应该会看到类似以下示例的输出：

   ```
   {
       "ServerSideEncryption": "AES256",
       "ETag": "\"e611693805e812ef37f96c9937605e69\"",
       "ChecksumSHA256": "QLl8R4i4+SaJlrl8ZIcutc5TbZtwt2NwB8lTXkd3GH0="
   }
   ```

1. 对于后续分段，相应地递增分段编号：

   ```
   aws s3api upload-part --bucket amzn-s3-demo-bucket1 --key 'census_data_file' --part-number <part-number> --body <file-path> --upload-id "<your-upload-id>" --checksum-algorithm SHA256
   ```

   例如，使用以下命令来上传第二个分段：

   ```
   aws s3api upload-part --bucket amzn-s3-demo-bucket1 --key 'census_data_file' --part-number 2 --body census-part01 --upload-id "cNV6KCSNANFZapz1LUGPC5XwUVi1n6yUoIeSP138sNOKPeMhpKQRrbT9k0ePmgoOTCj9K83T4e2Gb5hQvNoNpCKqyb8m3.oyYgQNZD6FNJLBZluOIUyRE.qM5yhDTdhz" --checksum-algorithm SHA256
   ```

   Amazon S3 将在响应的标头中返回每个已上传分段的实体标签（ETag）和额外的校验和。

1. 继续使用 `upload-part` 命令，直到上传了对象的所有分段。

## 步骤 5：列出分段上传的所有分段
<a name="list-parts-step5"></a>

要完成分段上传，您需要列出在这个特定分段上传任务中已经上传的所有分段。`list-parts` 命令的输出提供了诸如存储桶名称、键、上传 ID、分段编号、ETag、额外的校验和等信息。将此输出保存在文件中会很有帮助，这样您就可以在完成分段上传过程的下一步中使用它。可以使用以下方法创建名为 `parts.json` 的 JSON 输出文件。

**创建列出所有分段的文件**

1. 要生成包含所有已上传分段详细信息的 JSON 文件，请使用以下 `list-parts` 命令。将 ***amzn-s3-demo-bucket1*** 替换为实际的存储桶名称，并将 **<your-upload-id>** 替换为您在[步骤 3](#create-multipart-upload-step3) 中收到的上传 ID。有关 `list-parts` 命令的更多信息，请参阅《AWS Command Line Interface 用户指南》**中的 [https://docs.aws.amazon.com/cli/latest/reference/s3api/list-parts.html](https://docs.aws.amazon.com/cli/latest/reference/s3api/list-parts.html)。

   ```
   aws s3api list-parts --bucket amzn-s3-demo-bucket1 --key 'census_data_file' --upload-id <your-upload-id> --query '{Parts: Parts[*].{PartNumber: PartNumber, ETag: ETag, ChecksumSHA256: ChecksumSHA256}}' --output json > parts.json
   ```

   这样会生成一个名为 `parts.json` 的新文件。该文件采用 JSON 格式，包含所有已上传分段的信息。`parts.json` 文件包含分段上传的每个分段的基本信息，例如分段编号及其相应的 ETag 值，这些是完成分段上传过程所必需的。

1. 使用任何文本编辑器或通过终端打开 `parts.json`。以下是示例输出：

   ```
   {
       "Parts": [
           {
               "PartNumber": 1,
               "ETag": "\"3c3097f89e2a2fece47ac54b243c9d97\"",
               "ChecksumSHA256": "fTPVHfyNHdv5VkR4S3EewdyioXECv7JBxN+d4FXYYTw="
           },
           {
               "PartNumber": 2,
               "ETag": "\"03c71cc160261b20ab74f6d2c476b450\"",
               "ChecksumSHA256": "VDWTa8enjOvULBAO3W2a6C+5/7ZnNjrnLApa1QVc3FE="
           },
           {
               "PartNumber": 3,
               "ETag": "\"81ae0937404429a97967dffa7eb4affb\"",
               "ChecksumSHA256": "cVVkXehUlzcwrBrXgPIM+EKQXPUvWist8mlUTCs4bg8="
           }
       ]
   }
   ```

## 步骤 6：完成分段上传
<a name="complete-multipart-upload-step6"></a>

在分段上传的所有分段都上传完毕并且列出分段信息后，最后一步是完成分段上传。此步骤会在 S3 存储桶中将所有上传的分段合并成单个对象。

**注意**  
您可以在调用 `complete-multipart-upload` 之前，通过在请求中包含 `--checksum-sha256` 来计算对象的校验和。如果校验和不匹配，Amazon S3 就会让请求失败。有关更多信息，请参阅《AWS Command Line Interface 用户指南》**中的 [https://docs.aws.amazon.com/cli/latest/reference/s3api/complete-multipart-upload.html](https://docs.aws.amazon.com/cli/latest/reference/s3api/complete-multipart-upload.html)。

**完成分段上传**

要最终完成分段上传，请使用 `complete-multipart-upload` 命令。此命令需要用到[步骤 5](#list-parts-step5) 中创建的 `parts.json` 文件、存储桶名称以及上传 ID。将 **<*amzn-s3-demo-bucket1*>** 替换为存储桶名称，并将 **<your-upload-id>** 替换为 `parts.json` 的上传 ID。

```
aws s3api complete-multipart-upload --multipart-upload file://parts.json --bucket amzn-s3-demo-bucket1 --key 'census_data_file' --upload-id <your-upload-id>
```

以下是示例输出：

```
{
    "ServerSideEncryption": "AES256",
    "Location": "https://amzn-s3-demo-bucket1.s3.us-east-2.amazonaws.com/census_data_file",
    "Bucket": "amzn-s3-demo-bucket1",
    "Key": "census_data_file",
    "ETag": "\"f453c6dccca969c457efdf9b1361e291-3\"",
    "ChecksumSHA256": "aI8EoktCdotjU8Bq46DrPCxQCGuGcPIhJ51noWs6hvk=-3"
}
```

**注意**  
此时请勿删除各个分段文件。您还需要使用各个分段来对它们执行校验和，从而验证合并在一起的对象的完整性。

## 步骤 7：确认对象上传到存储桶
<a name="confirm-upload-step7"></a>

完成分段上传后，您可以验证对象已成功地上传到 S3 存储桶。要列出存储桶中的对象并确认新上传的文件已经存在，请使用 `list-objects-v2` 命令。

**列出上传的对象**

要列出存储桶中的对象，请使用 `list-objects-v2` 命令。将 ***amzn-s3-demo-bucket1*** 替换为实际存储桶名称：

```
aws s3api list-objects-v2 --bucket amzn-s3-demo-bucket1
```

此命令将返回存储桶中对象的列表。在对象列表中查找您上传的文件（例如 `census_data_file`）。

有关更多信息，请参阅《AWS Command Line Interface用户指南》**中 `list-objects-v2` 命令的 [Examples](https://docs.aws.amazon.com/cli/latest/reference/s3api/list-objects-v2.html) 部分。

## 步骤 8：使用 MD5 校验和验证对象完整性
<a name="verify-object-integrity-step8"></a>

在上传对象时，可以指定校验和算法以供 Amazon S3 使用。默认情况下，Amazon S3 将 MD5 字节摘要存储为对象的 ETag。对于分段上传，ETag 不是完整对象的校验和，而是每个单独分段的校验和组合。

**使用 MD5 校验和验证对象完整性**

1. 要检索已上传对象的 ETag，请执行 `head-object` 请求：

   ```
   aws s3api head-object --bucket amzn-s3-demo-bucket1 --key census_data_file
   ```

   以下是示例输出：

   ```
   {
       "AcceptRanges": "bytes",
       "LastModified": "2024-07-26T19:04:13+00:00",
       "ContentLength": 16106127360,
       "ETag": "\"f453c6dccca969c457efdf9b1361e291-3\"",
       "ContentType": "binary/octet-stream",
       "ServerSideEncryption": "AES256",
       "Metadata": {}
   }
   ```

   此 ETag 的末尾附有“-3”。这表示对象是使用分段上传分为三个分段进行上传的。

1. 接下来，使用 `md5sum` 命令计算每个分段的 MD5 校验和。请确保提供指向分段文件的正确路径：

   ```
   md5sum census-part*
   ```

   以下是示例输出：

   ```
   e611693805e812ef37f96c9937605e69 census-part00
   63d2d5da159178785bfd6b6a5c635854 census-part01
   95b87c7db852451bb38b3b44a4e6d310 census-part02
   ```

1. 对于此步骤，手动将 MD5 哈希值合并为一个字符串。然后，运行以下命令，将字符串转换为二进制并计算二进制值的 MD5 校验和：

   ```
   echo "e611693805e812ef37f96c9937605e6963d2d5da159178785bfd6b6a5c63585495b87c7db852451bb38b3b44a4e6d310" | xxd -r -p | md5sum
   ```

   以下是示例输出：

   ```
   f453c6dccca969c457efdf9b1361e291 -
   ```

   此哈希值应与[步骤 1](#create-large-file-step1) 中原始 ETag 值的哈希值相匹配，这可验证 `census_data_file` 对象的完整性。

当您指示 Amazon S3 使用其他校验和时，Amazon S3 会计算每个分段的校验和值并存储这些值。如果您想检索仍在进行的分段上传的各个分段的校验和值，可以使用 `list-parts`。

有关校验和如何处理分段上传对象的更多信息，请参阅[在 Amazon S3 中检查对象完整性](checking-object-integrity.md)。

## 步骤 9：使用额外的校验和验证对象完整性
<a name="verify-object-integrity-sha256-step9"></a>

在本步骤中，教程使用 SHA-256 作为额外的校验和来验证对象完整性。如果您使用了不同的额外校验和，请改用该校验和值。

**使用 SHA256 验证对象完整性**

1. 在终端中运行以下命令（包括 `--checksum-mode enabled` 参数），以显示对象的 `ChecksumSHA256` 值：

   ```
   aws s3api head-object --bucket amzn-s3-demo-bucket1 --key census_data_file --checksum-mode enabled
   ```

   以下是示例输出：

   ```
   {
       "AcceptRanges": "bytes",
       "LastModified": "2024-07-26T19:04:13+00:00",
       "ContentLength": 16106127360,
       "ChecksumSHA256": "aI8EoktCdotjU8Bq46DrPCxQCGuGcPIhJ51noWs6hvk=-3",
       "ETag": "\"f453c6dccca969c457efdf9b1361e291-3\"",
       "ContentType": "binary/octet-stream",
       "ServerSideEncryption": "AES256",
       "Metadata": {}
   }
   ```

1. 使用以下命令将各个分段的 `ChecksumSHA256` 值解码为 base64，然后将其保存到名为 `outfile` 的二进制文件中。这些值可以在 `parts.json` 文件中找到。将示例 base64 字符串替换为实际的 `ChecksumSHA256` 值。

   ```
   echo "QLl8R4i4+SaJlrl8ZIcutc5TbZtwt2NwB8lTXkd3GH0=" | base64 --decode >> outfile
   echo "xCdgs1K5Bm4jWETYw/CmGYr+m6O2DcGfpckx5NVokvE=" | base64 --decode >> outfile
   echo "f5wsfsa5bB+yXuwzqG1Bst91uYneqGD3CCidpb54mAo=" | base64 --decode >> outfile
   ```

1. 运行以下命令计算 `outfile` 的 SHA256 校验和：

   ```
   sha256sum outfile
   ```

   以下是示例输出：

   ```
   688f04a24b42768b6353c06ae3a0eb3c2c50086b8670f221279d67a16b3a86f9 outfile
   ```

   在下一步中，获取哈希值并将其转换为二进制值。此二进制值应与[步骤 1](#create-large-file-step1) 中的 `ChecksumSHA256` 值相匹配。

1. 将[步骤 3](#create-multipart-upload-step3) 中的 SHA256 校验和转换为二进制，然后将其编码为 base64，来验证它与[步骤 1](#create-large-file-step1) 中的 `ChecksumSHA256` 值相匹配：

   ```
   echo "688f04a24b42768b6353c06ae3a0eb3c2c50086b8670f221279d67a16b3a86f9" | xxd -r -p | base64
   ```

   以下是示例输出：

   ```
   aI8EoktCdotjU8Bq46DrPCxQCGuGcPIhJ51noWs6hvk=
   ```

   此输出应确认 base64 输出与 `head-object` 命令输出中的 `ChecksumSHA256` 值相匹配。如果输出与校验和值匹配，则该对象有效。

**重要**  
当您指示 Amazon S3 使用额外的校验和时，Amazon S3 会计算每个分段的校验和值并存储这些值。
如果您想检索仍在进行的分段上传的各个分段的校验和值，可以使用 `list-parts` 命令。

## 步骤 10：清除资源
<a name="clean-up-step10"></a>

如果要清理在本教程中创建的文件，请使用以下方法。有关删除上传到 S3 存储桶的文件的说明，请参阅[删除 Amazon S3 对象](DeletingObjects.md)。

**删除[步骤 1](#create-large-file-step1) 中创建的本地文件：**

要删除您为分段上传创建的文件，请从工作目录中运行以下命令：

```
rm census-data.bin census-part* outfile parts.json
```

# Amazon S3 分段上传限制
<a name="qfacts"></a>

分段上传允许将单个对象作为一组分段上传。每个分段都是对象数据的连续部分。上传完所有的对象分段后，Amazon S3 将汇集这些分段并创建对象。一般而言，如果您的对象大小达到了 100 MB，您应该考虑使用分段上传，而不是在单个操作中上传对象。有关分段上传的更多信息，请参阅 [在 Amazon S3 中使用分段上传来上传和复制对象](mpuoverview.md)。

下表提供了分段上传的核心规范。其中包括最大对象大小、最大分段数、最大分段大小等等。未对分段上传的最后一段施加最小大小限制。


| Item | 规范 | 
| --- | --- | 
| 最大对象大小 | 48.8 TiB  | 
| 每次上传的分段的最大数量 | 10000 | 
| 分段编号 | 1 到 10,000（含） | 
| 分段大小 | 5MiB 到 5GiB。未对分段上传的最后一段施加最小大小限制。 | 
| 列出分段请求返回的分段的最大数量 | 1000  | 
| 在列出分段上传请求中返回的分段的最大数量 | 1000  | 