All Products
Search
Document Center

Object Storage Service:Copy objects

Last Updated:Oct 18, 2023

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

Usage notes

  • In this topic, the public endpoint of the China (Hangzhou) region is used. If you want to access OSS by using other Alibaba Cloud services in the same region as OSS, use an internal endpoint. For more information about the regions and endpoints supported by OSS, see Regions and endpoints.

  • In this topic, an OSSClient instance is created by using an OSS endpoint. If you want to create an OSSClient instance by using custom domain names or Security Token Service (STS), see Initialization.

  • To copy an object, you must have read permissions on the source object and read and write permissions on the destination bucket.

  • Make sure that no retention policies are configured for the source bucket and the destination bucket. Otherwise, the error message The object you specified is immutable. is returned.

  • The source bucket and 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 sample 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";
// Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured. 
var accessKeyId = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_ID");
var accessKeySecret = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_SECRET");
// Specify the name of the source bucket. Example: srcexamplebucket. 
var sourceBucket = "srcexamplebucket";
// Specify the full path of the source object. Do not include the bucket name in the full path. Example: srcdir/scrobject.txt. 
var sourceObject = "srcdir/scrobject.txt";
// Specify the name of the destination bucket. The destination bucket must be in the same region as the source bucket. Example: destbucket. 
var targetBucket = "destbucket";
// Specify the full path of the destination object. Do not include the bucket name in the full path. 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();
    // Specify user metadata. The user metadata is stored as key-value pairs. For example, the key is mk1 and the value is mv1. 
    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 whose size is larger than 1 GB, 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;
    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";
    // Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured. 
    var accessKeyId = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_ID");
    var accessKeySecret = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_SECRET");
    // Specify the name of the source bucket. Example: srcexamplebucket. 
    var sourceBucket = "srcexamplebucket";
    // Specify the full path of the source object. Do not include the bucket name in the full path. Example: srcdir/scrobject.txt. 
    var sourceObject = "srcdir/scrobject.txt";
    // Specify the name of the destination bucket. The destination bucket must be in the same region as the source bucket. Example: destbucket. 
    var targetBucket = "destbucket";
    // Specify the full path of the destination object. Do not include the bucket name in the full path. 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 call the InitiateMultipartUploadRequest operation 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 call 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 copy 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 partETags. OSS verifies the validity of 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";
    // Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured. 
    var accessKeyId = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_ID");
    var accessKeySecret = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_SECRET");
    // Specify the name of the source bucket. Example: srcexamplebucket. 
    var sourceBucket = "srcexamplebucket";
    // Specify the full path of the source object. Do not include the bucket name in the full path. Example: srcdir/scrobject.txt. 
    var sourceObject = "srcdir/scrobject.txt";
    // Specify the name of the destination bucket. The destination bucket must be in the same region as the source bucket. Example: destbucket. 
    var targetBucket = "destbucket";
    // Specify the full path of the destination object. Do not include the bucket name in the full path. 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.