复制对象

CopyObject操作用于创建一个已经在媒体存储中的对象。使用CopyOoject可以复制单个最大为5GB的对象,如果需要复制更大的对象,可以使用UploadPartCopy操作。执行CopyObject操作,必须具有对被拷贝对象的READ权限和对目标bucket的WRITE权限。

拷贝生成的对象默认保留原对象的元数据信息,也可以才CopyObject操作中指定新的元数据。拷贝生成的对象不会保留原来的ACL信息,该对象默认是发起CopyObject操作的用户私有的。

CopyObject操作默认拷贝原对象的当前版本数据,如果需要拷贝原对象的指定版本,可以在CopySource中加入versionId来拷贝指定的Object版本,如果原对象的versionId为删除标记,则不会被拷贝。

示例代码:

using System;
using System.Threading.Tasks;
using Amazon.Runtime;
using Amazon.S3;
using Amazon.S3.Model;

namespace DotNetSDK.ObjectOperation
{
    public class CopyObjectExample
    {
        public static async Task CopyObject()
        {
            var accessKey = "YOUR_ACCESS_KEY";
            var secretKey = "YOUR_SECRET_KEY";
            var endpoint = "YOUR_ENDPOINT";
            var sourceBucket = "SOURCE_BUCKET";
            var sourceKey = "SOURCE_KEY";
            var destinationBucket = "DESTINATION_BUCKET";
            var destinationKey = "DESTINATION_KEY";
            try
            {
                var credentials = new BasicAWSCredentials(accessKey, secretKey);
                var conf = new AmazonS3Config
                {
                    ServiceURL = endpoint
                };
                var s3Client = new AmazonS3Client(credentials, conf);
                var copyObjectRequest = new CopyObjectRequest()
                {
                    SourceBucket = sourceBucket,
                    SourceKey = sourceKey,
                    DestinationBucket = destinationBucket,
                    DestinationKey = destinationKey
                };
                var result = await s3Client.CopyObjectAsync(copyObjectRequest);
                if (result.HttpStatusCode != System.Net.HttpStatusCode.OK)
                {
                    Console.WriteLine("fail to copy object, HttpStatusCode:{0}, ErrorCode:{1}.", (int) result.HttpStatusCode, result.HttpStatusCode);
                    return;
                }

                Console.WriteLine("copy object from {0}/{1} to {2}/{3}.", sourceBucket, sourceKey, destinationBucket, destinationKey);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }
    }
}

CopyObjectRequest可设置的参数如下:

参数 类型 说明 是否必要
CannedACL S3CannedACL 拷贝后对象的预定义的标准ACL信息。
DestinationBucket string 放置拷贝生成对象的bucket的名称。
DestinationKey string 拷贝生成对象的key。
SourceBucket string 放置被拷贝对象的bucket的名称。
SourceKey string 被拷贝对象的key。
Metadata MetadataCollection 拷贝生成对象的元数据信息。
MetadataDirective S3MetadataDirective 指定拷贝生成的对象的元数据信息来自被拷贝对象,还是来自请求中附带的信息。
TagSet List<Tag> 拷贝生成对象的标签信息。
SourceVersionId string 指定被拷贝对象的版本信息,如果不指定,默认拷贝对象的当前版本。
WebsiteRedirectLocation string 如果bucket被配置用于提供网站的静态数据,该参数可以用于设置访问对象时候重定向到当前bucket下的其他对象或者外部的URL。

CopyObject返回的结果如下:

参数 类型 说明
ETag string 拷贝生成对象的ETag。
LastModified string 拷贝生成对象的最新修改时间。

响应结果:

HTTP状态码 响应码 描述
200 OK 操作成功。
400 BadRequest 拷贝的对象太大或者对象的名字不合法。
403 Forbidden 用户没有权限执行操作。
404 NotFound 设置的bucket或者对象key不存在。

分段拷贝

CopyPart操作可以从一个已存在的对象中拷贝指定片段的数据,当拷贝的对象大小超过5GB,必须使用UploadPartCopy操作完成对象的复制。除了最后一个片段外,每个拷贝片段的大小范围是[5MB,5GB]。在一个在拷贝大对象之前,需要使用CompleteMultiPartUpload操作获取一个upload ID,在完成拷贝操作之后,需要使用CompleteMultipartUpload操作组装已拷贝的片段成为一个对象。

代码示例:

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

namespace DotNetSDK.ObjectOperation
{
    public class CopyPartsExample
    {
        public static async Task CopyParts()
        {
            var accessKey = "YOUR_ACCESS_KEY";
            var secretKey = "YOUR_SECRET_KEY";
            var endpoint = "YOUR_ENDPOINT";
            var sourceBucket = "SOURCE_BUCKET";
            var sourceKey = "SOURCE_KEY";
            var destinationBucket = "DESTINATION_BUCKET";
            var destinationKey = "DESTINATION_KEY";
            try
            {
                var credentials = new BasicAWSCredentials(accessKey, secretKey);
                List<CopyPartResponse> copyResponses = new List<CopyPartResponse>();
                var conf = new AmazonS3Config
                {
                    ServiceURL = endpoint
                };
                var s3Client = new AmazonS3Client(credentials, conf);
                // 发起一个分段上传操作请求,获取upload id
                Task<InitiateMultipartUploadResponse> taskInitiateMultipartUploadResp = s3Client.InitiateMultipartUploadAsync(new InitiateMultipartUploadRequest()
                {
                    BucketName = destinationBucket,
                    Key = destinationKey
                });
                var uploadId = taskInitiateMultipartUploadResp.Result.UploadId;
                Console.WriteLine("upload id: {0}", uploadId);
                // 获取被拷贝对象的大小
                GetObjectMetadataRequest getObjectMetadataRequest = new GetObjectMetadataRequest
                {
                    BucketName = sourceBucket,
                    Key = sourceKey
                };
                var getObjectMetadataResponse = await s3Client.GetObjectMetadataAsync(getObjectMetadataRequest);
                long objectSize = getObjectMetadataResponse.ContentLength;
                // 拷贝分段
                long partSize = 5 * (long) Math.Pow(2, 20); // 5 MB.
                long bytePosition = 0;
                for (int i = 1; bytePosition < objectSize; i++)
                {
                    CopyPartRequest copyPartRequest = new CopyPartRequest
                    {
                        DestinationBucket = destinationBucket,
                        DestinationKey = destinationKey,
                        SourceBucket = sourceBucket,
                        SourceKey = sourceKey,
                        UploadId = uploadId,
                        FirstByte = bytePosition,
                        LastByte = bytePosition + partSize - 1 >= objectSize ? objectSize - 1 : bytePosition + partSize - 1,
                        PartNumber = i
                    };
                    var copyPartResponse = await s3Client.CopyPartAsync(copyPartRequest);
                    copyResponses.Add(copyPartResponse);
                    bytePosition += partSize;
                }

                // 完成拷贝分段
                CompleteMultipartUploadRequest completeRequest =
                    new CompleteMultipartUploadRequest
                    {
                        BucketName = destinationBucket,
                        Key = destinationKey,
                        UploadId = uploadId
                    };
                completeRequest.AddPartETags(copyResponses);
                CompleteMultipartUploadResponse completeUploadResponse = await s3Client.CompleteMultipartUploadAsync(completeRequest);
                if (completeUploadResponse.HttpStatusCode != System.Net.HttpStatusCode.OK)
                {
                    Console.WriteLine("fail to get copy parts, HttpStatusCode:{0}, ErrorCode:{1}.", (int) completeUploadResponse.HttpStatusCode, completeUploadResponse.HttpStatusCode);
                    return;
                }

                Console.WriteLine("copy object from {0}/{1} to {2}/{3}.", sourceBucket, sourceKey, destinationBucket, destinationKey);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }
    }
}

CopyPartRequest可设置的参数如下:

参数 类型 说明 是否必要
DestinationBucket string 放置拷贝生成对象的bucket的名称。
DestinationKey string 拷贝生成对象的key。
SourceBucket string 放置被拷贝对象的bucket的名称。
SourceKey string 被拷贝对象的key。
UploadId string 与本次拷贝操作相应的分段上传Id。
SourceVersionId string 指定被拷贝对象的版本信息,如果不指定,默认拷贝对象的当前版本。

CopyPart返回的结果如下:

参数 类型 说明
ContentLength long 拷贝片段的长度。
ETag string 拷贝片段的ETag。
LastModified string 拷贝片段的最新修改时间。
PartNumber int 拷贝片段的序号。

响应结果:

HTTP状态码 响应码 描述
200 OK 操作成功。
400 BadRequest 拷贝的对象太大或者对象的名字不合法。
403 Forbidden 用户没有权限执行操作。
404 NotFound 设置的bucket或者对象key不存在。