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 from other Alibaba Cloud services in the same region as OSS, use an internal endpoint. For more information about OSS regions and endpoints, 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 file
The following code provides an example on how to copy a small object:
using Aliyun.OSS;
using Aliyun.OSS.Common;
// Specify the Endpoint for the region where the bucket is located. For example, if the bucket is 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. The full path cannot contain the bucket name. Example: srcdir/scrobject.txt.
var sourceObject = "srcdir/scrobject.txt";
// Specify the name of the destination bucket, which must be 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 region where the bucket is located. For example, if the bucket is in the China (Hangzhou) region, set the region to cn-hangzhou.
const string region = "cn-hangzhou";
// Create a ClientConfiguration instance and modify the default parameters as needed.
var conf = new ClientConfiguration();
// Use Signature V4.
conf.SignatureVersion = SignatureVersion.V4;
// Create an OssClient instance.
var client = new OssClient(endpoint, accessKeyId, accessKeySecret, conf);
client.SetRegion(region);
try
{
var metadata = new ObjectMetadata();
// Set custom metadata. Custom metadata is a key-value pair. For example, set the key to mk1 and the value to mv1.
metadata.AddHeader("mk1", "mv1");
metadata.AddHeader("mk2", "mv2");
var req = new CopyObjectRequest(sourceBucket, sourceObject, targetBucket, targetObject)
{
// If NewObjectMetadata is null, the metadata of the source object is copied (COPY mode). If NewObjectMetadata is not null, the metadata of the source object is overwritten (REPLACE mode).
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 file
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:
Use the InitiateMultipartUploadRequest method to initialize a multipart upload event.
Use the UploadPartCopy method to copy parts.
Use the CompleteMultipartUpload method to complete the object copy.
The following code shows how to perform a multipart copy:
using Aliyun.OSS; using Aliyun.OSS.Common; // Specify the Endpoint for the region where the bucket is located. For example, if the bucket is 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. The full path cannot contain the bucket name. Example: srcdir/scrobject.txt. var sourceObject = "srcdir/scrobject.txt"; // Specify the name of the destination bucket, which must be 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; // Specify the region where the bucket is located. For example, if the bucket is in the China (Hangzhou) region, set the region to cn-hangzhou. const string region = "cn-hangzhou"; // Create a ClientConfiguration instance and modify the default parameters as needed. var conf = new ClientConfiguration(); // Use Signature V4. conf.SignatureVersion = SignatureVersion.V4; // Create an OssClient instance. var client = new OssClient(endpoint, accessKeyId, accessKeySecret, conf); client.SetRegion(region); try { // Initialize the 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); // Print the upload ID. uploadId = result.UploadId; Console.WriteLine("Init multipart upload succeeded, Upload Id: {0}", result.UploadId); // Calculate the 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. 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. You can use UploadPartCopyRequest to specify conditions. var uploadPartCopyRequest = new UploadPartCopyRequest(targetBucket, targetObject, sourceBucket, sourceObject, uploadId) { PartSize = size, PartNumber = i + 1, // BeginIndex specifies the starting position of the part to be copied. 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. var completeMultipartUploadRequest = new CompleteMultipartUploadRequest(targetBucket, targetObject, uploadId); // partETags is a list of PartETags saved during the multipart upload. After OSS receives this list, it verifies each part. If all parts are valid, OSS combines them 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 copy task is interrupted, you can resume it from the breakpoint.
The following code shows how to perform a resumable copy:
using Aliyun.OSS; // Specify the Endpoint for the region where the bucket is located. For example, if the bucket is 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. The full path cannot contain the bucket name. Example: srcdir/scrobject.txt. var sourceObject = "srcdir/scrobject.txt"; // Specify the name of the destination bucket, which must be 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 file that records the copy results. The progress information is saved to this file. If the copy task fails, it resumes from the recorded breakpoint. After the copy is complete, this file is deleted. var checkpointDir = @"yourCheckpointDir"; // Specify the region where the bucket is located. For example, if the bucket is in the China (Hangzhou) region, set the region to cn-hangzhou. const string region = "cn-hangzhou"; // Create a ClientConfiguration instance and modify the default parameters as needed. var conf = new ClientConfiguration(); // Use Signature V4. conf.SignatureVersion = SignatureVersion.V4; // Create an OssClient instance. var client = new OssClient(endpoint, accessKeyId, accessKeySecret, conf); client.SetRegion(region); try { var request = new CopyObjectRequest(sourceBucket, sourceObject, targetBucket, targetObject); // The checkpointDir directory saves the intermediate state for resumable copy. This allows the task to resume after a failure. If checkpointDir is null, the resumable copy feature is disabled, and the copy task starts over each time. 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, see GitHub.
For more information about the API operation that is used to copy a small object, see CopyObject.
Copy a large object
For the complete sample code that is used to copy a large object, see GitHub.
For more information about the API operation that is used to copy a large object, see UploadPartCopy.
Resumable copy
For the complete sample code that is used for a resumable copy, see GitHub.