

# 使用分段上传复制对象
<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);
            }
        }
    }
}
```

------