This topic describes how to copy an object within a bucket or across buckets in the same region.

Precautions

  • To copy an object, you must have read permissions on the source object and read and write permissions on the destination bucket.
  • The source bucket and the destination bucket must have no retention policies configured. Otherwise, the error message The object you specified is immutable. is returned.
  • The source bucket and the destination bucket must be in the same region. For example, objects cannot be copied from a bucket located in the China (Hangzhou) region to another bucket located in the China (Qingdao) region.

Copy a small object

The following code provides an example on how to copy a small object:

using Aliyun.OSS;
using Aliyun.OSS.Common;

// Specify the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com. 
var endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// Security risks may arise if you use the AccessKey pair of an Alibaba Cloud account to access Object Storage Service (OSS) because the account has permissions on all API operations. We recommend that you use a RAM user to call API operations or perform routine O&M. To create a RAM user, log on to the RAM console. 
var accessKeyId = "yourAccessKeyId";
var accessKeySecret = "yourAccessKeySecret";
// Specify the name of the source bucket. Example: srcexamplebucket. 
var sourceBucket = "srcexamplebucket";
// Specify the full path of the source object. The full path cannot contain the bucket name. Example: srcdir/scrobject.txt. 
var sourceObject = "srcdir/scrobject.txt";
// Specify the name of the destination bucket. The destination bucket must be located in the same region as the source bucket. Example: destbucket. 
var targetBucket = "destbucket";
// Specify the full path of the destination object. The full path cannot contain the bucket name. Example: destdir/destobject.txt. 
var targetObject = "destdir/destobject.txt";

// Create an OssClient instance. 
var client = new OssClient(endpoint, accessKeyId, accessKeySecret);
try
{
    var metadata = new ObjectMetadata();
    metadata.AddHeader("mk1", "mv1");
    metadata.AddHeader("mk2", "mv2");
    var req = new CopyObjectRequest(sourceBucket, sourceObject, targetBucket, targetObject)
    {
        // If the value of NewObjectMetadata is null, the COPY mode is used and the metadata of the source object is copied to the destination object. If the value of NewObjectMetadata is not null, the REPLACE mode is used and the metadata of the destination object is overwritten by the metadata specified in the request. 
        NewObjectMetadata = metadata 
    };
    // Copy the object. 
    client.CopyObject(req);
    Console.WriteLine("Copy object succeeded");
}
catch (OssException ex)
{
    Console.WriteLine("Failed with error code: {0}; Error info: {1}. \nRequestID: {2} \tHostID: {3}",
        ex.ErrorCode, ex.Message, ex.RequestId, ex.HostId);
}
catch (Exception ex)
{
    Console.WriteLine("Failed with error info: {0}", ex.Message);
}

Copy a large object

  • Copy objects by using multipart copy

    To copy an object that is larger than 1 GB in size, you must split the object into parts and sequentially copy the parts by using UploadPartCopy. To implement multipart copy, perform the following steps:

    1. Call the InitiateMultipartUploadRequest method to initiate a multipart copy task.
    2. Call the UploadPartCopy method to perform multipart copy.
    3. Call the CompleteMultipartUpload method to complete the multipart copy task.

    The following code provides an example on how to perform multipart copy:

    using Aliyun.OSS;
    // Specify the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com. 
    var endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
    // Security risks may arise if you use the AccessKey pair of an Alibaba Cloud account to access OSS because the account has permissions on all API operations. We recommend that you use a RAM user to call API operations or perform routine O&M. To create a RAM user, log on to the RAM console. 
    var accessKeyId = "yourAccessKeyId";
    var accessKeySecret = "yourAccessKeySecret";
    // Specify the name of the source bucket. Example: srcexamplebucket. 
    var sourceBucket = "srcexamplebucket";
    // Specify the full path of the source object. The full path cannot contain the bucket name. Example: srcdir/scrobject.txt. 
    var sourceObject = "srcdir/scrobject.txt";
    // Specify the name of the destination bucket. The destination bucket must be located in the same region as the source bucket. Example: destbucket. 
    var targetBucket = "destbucket";
    // Specify the full path of the destination object. The full path cannot contain the bucket name. Example: destdir/destobject.txt. 
    var targetObject = "destdir/destobject.txt";
    var uploadId = "";
    var partSize = 50 * 1024 * 1024;
    // Create an OssClient instance. 
    var client = new OssClient(endpoint, accessKeyId, accessKeySecret);
    try
    {
        // Initiate a multipart copy task. You can use InitiateMultipartUploadRequest to specify the metadata of the destination object. 
        var request = new InitiateMultipartUploadRequest(targetBucket, targetObject);
        var result = client.InitiateMultipartUpload(request);
        // Display the upload ID. 
        uploadId = result.UploadId;
        Console.WriteLine("Init multipart upload succeeded, Upload Id: {0}", result.UploadId);
        // Calculate the total number of parts. 
        var metadata = client.GetObjectMetadata(sourceBucket, sourceObject);
        var fileSize = metadata.ContentLength;
        var partCount = (int)fileSize / partSize;
        if (fileSize % partSize != 0)
        {
            partCount++;
        }
        // Start the multipart copy task. 
        var partETags = new List<PartETag>();
        for (var i = 0; i < partCount; i++)
        {
            var skipBytes = (long)partSize * i;
            var size = (partSize < fileSize - skipBytes) ? partSize : (fileSize - skipBytes);
            // Create an UploadPartCopyRequest object. You can use UploadPartCopyRequest to specify conditions. 
            var uploadPartCopyRequest = new UploadPartCopyRequest(targetBucket, targetObject, sourceBucket, sourceObject, uploadId)
                {
                    PartSize = size,
                    PartNumber = i + 1,
                    // Use BeginIndex to find the start position to upload the part. 
                    BeginIndex = skipBytes
                };
            // Call the UploadPartCopy method to copy each part. 
            var uploadPartCopyResult = client.UploadPartCopy(uploadPartCopyRequest);
            Console.WriteLine("UploadPartCopy : {0}", i);
            partETags.Add(uploadPartCopyResult.PartETag);
        }
        // Complete the multipart copy task. 
        var completeMultipartUploadRequest =
        new CompleteMultipartUploadRequest(targetBucket, targetObject, uploadId);
        // partETags is a list of partETag. OSS verifies each part after it receives partETags. After all parts are verified, OSS combines these parts into a complete object. 
        foreach (var partETag in partETags)
        {
            completeMultipartUploadRequest.PartETags.Add(partETag);
        }
        var completeMultipartUploadResult = client.CompleteMultipartUpload(completeMultipartUploadRequest);
        Console.WriteLine("CompleteMultipartUpload succeeded");
    }
    catch (OssException ex)
    {
        Console.WriteLine("Failed with error code: {0}; Error info: {1}. \nRequestID: {2} \tHostID: {3}",
            ex.ErrorCode, ex.Message, ex.RequestId, ex.HostId);
    }
    catch (Exception ex)
    {
        Console.WriteLine("Failed with error info: {0}", ex.Message);
    }
  • Resumable copy

    If a resumable copy task is interrupted, you can continue the copy task.

    The following code provides an example on how to copy an object by using resumable copy:

    using Aliyun.OSS;
    // Specify the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com. 
    var endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
    // Security risks may arise if you use the AccessKey pair of an Alibaba Cloud account to access OSS because the account has permissions on all API operations. We recommend that you use a RAM user to call API operations or perform routine O&M. To create a RAM user, log on to the RAM console. 
    var accessKeyId = "yourAccessKeyId";
    var accessKeySecret = "yourAccessKeySecret";
    // Specify the name of the source bucket. Example: srcexamplebucket. 
    var sourceBucket = "srcexamplebucket";
    // Specify the full path of the source object. The full path cannot contain the bucket name. Example: srcdir/scrobject.txt. 
    var sourceObject = "srcdir/scrobject.txt";
    // Specify the name of the destination bucket. The destination bucket must be located in the same region as the source bucket. Example: destbucket. 
    var targetBucket = "destbucket";
    // Specify the full path of the destination object. The full path cannot contain the bucket name. Example: destdir/destobject.txt. 
    var targetObject = "destdir/destobject.txt";
    // Specify the checkpoint file that records the results of the resumable copy task. This file stores information about the copy progress. If an object fails to be copied, the next copy operation continues based on the recorded progress. After the object is copied, the checkpoint file is deleted. 
    var checkpointDir = @"yourCheckpointDir";
    // Create an OssClient instance. 
    var client = new OssClient(endpoint, accessKeyId, accessKeySecret);
    try
    {
        var request = new CopyObjectRequest(sourceBucket, sourceObject, targetBucket, targetObject);
        // Specify the checkpointDir directory in which the checkpoint file is stored. The checkpoint file records the state of the resumable copy task and can be used to resume the task in case of failures. If you set checkpointDir to null, resumable copy does not take effect, and the object must be copied again from the start if it fails to be copied. 
        client.ResumableCopyObject(request, checkpointDir);
        Console.WriteLine("Resumable copy new object:{0} succeeded", request.DestinationKey);
    }
    catch (Exception ex)
    {
        Console.WriteLine("Resumable copy new object failed, {0}", ex.Message);
    }

References

  • Copy a small object
    • For the complete sample code that is used to copy a small object, visit GitHub.
    • For more information about the API operation that you can call to copy a small object, see CopyObject.
  • Copy a large object
    • For the complete sample code that is used to copy a large object, visit GitHub.
    • For more information about the API operation that you can call to copy a large object, see UploadPartCopy.
  • Resumable copy

    For the complete sample code that is used to perform resumable copy, visit GitHub.