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 by using custom domain names or Security Token Service (STS), see Create an OSSClient instance.
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 in a bucket located in the China (Hangzhou) region cannot be copied to another bucket located in the China (Qingdao) region.
Copy a small object
You can call client.CopyObject to copy an object that is smaller than 1 GB from a source bucket to a destination bucket within the same region. The following table describes how to configure parameters when you call client.CopyObject.
Configuration method | Description |
CopyObjectOutcome OssClient::CopyObject(const CopyObjectRequest &request) | Allows you to specify the metadata of the destination object and copy conditions. If the URLs of the source object and destination object are the same, the metadata that is specified in the request replaces the metadata of the source object. |
The following code provides an example on how to copy a small object:
#include <alibabacloud/oss/OssClient.h>
using namespace AlibabaCloud::OSS;
int main(void)
{
/* Initialize information about the account that is used to access 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. */
std::string Endpoint = "yourEndpoint";
/* Specify the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the region to cn-hangzhou. */
std::string Region = "yourRegion";
/* Specify the name of the source bucket. Example: srcexamplebucket. */
std::string SourceBucketName = "srcexamplebucket";
/* Specify the name of the destination bucket. The destination bucket must be located in the same region as the source bucket. Example: destbucket. */
std::string CopyBucketName = "destbucket";
/* Specify the full path of the source object. Do not include the bucket name in the full path. Example: srcdir/scrobject.txt. */
std::string SourceObjectName = "srcdir/scrobject.txt";
/* Specify the full path of the destination object. Do not include the bucket name in the full path. Example: destdir/destobject.txt. */
std::string CopyObjectName = "destdir/destobject.txt";
/* Initialize resources such as network resources. */
InitializeSdk();
ClientConfiguration conf;
conf.signatureVersion = SignatureVersionType::V4;
/* 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. */
auto credentialsProvider = std::make_shared<EnvironmentVariableCredentialsProvider>();
OssClient client(Endpoint, credentialsProvider, conf);
client.SetRegion(Region);
CopyObjectRequest request(CopyBucketName, CopyObjectName);
request.setCopySource(SourceBucketName, SourceObjectName);
/* Copy the object. */
auto outcome = client.CopyObject(request);
if (!outcome.isSuccess()) {
/* Handle exceptions. */
std::cout << "CopyObject fail" <<
",code:" << outcome.error().Code() <<
",message:" << outcome.error().Message() <<
",requestId:" << outcome.error().RequestId() << std::endl;
return -1;
}
/* Release resources such as network resources. */
ShutdownSdk();
return 0;
}
Copy a large object
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 client.InitiateMultipartUpload to initiate a multipart copy task.
Use client.UploadPartCopy to copy the parts. All parts must be larger than 100 KB, except for the last part.
Use client.CompleteMultipartUpload to complete the multipart copy task.
The following code provides an example on how to copy a large object:
#include <alibabacloud/oss/OssClient.h>
using namespace AlibabaCloud::OSS;
int main(void)
{
/* Initialize information about the account that is used to access 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. */
std::string Endpoint = "yourEndpoint";
/* Specify the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the region to cn-hangzhou. */
std::string Region = "yourRegion";
/* Specify the name of the source bucket. Example: srcexamplebucket. */
std::string SourceBucketName = "srcexamplebucket";
/* Specify the name of the destination bucket. The destination bucket must be located in the same region as the source bucket. Example: destbucket. */
std::string CopyBucketName = "destbucket";
/* Specify the full path of the source object. Do not include the bucket name in the full path. Example: srcdir/scrobject.txt. */
std::string SourceObjectName = "srcdir/scrobject.txt";
/* Specify the full path of the destination object. Do not include the bucket name in the full path. Example: destdir/destobject.txt. */
std::string CopyObjectName = "destdir/destobject.txt";
/* Initialize resources such as network resources. */
InitializeSdk();
ClientConfiguration conf;
conf.signatureVersion = SignatureVersionType::V4;
/* 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. */
auto credentialsProvider = std::make_shared<EnvironmentVariableCredentialsProvider>();
OssClient client(Endpoint, credentialsProvider, conf);
client.SetRegion(Region);
auto getObjectMetaReq = GetObjectMetaRequest(SourceBucketName, SourceObjectName);
auto getObjectMetaResult = client.GetObjectMeta(getObjectMetaReq);
if (!getObjectMetaResult.isSuccess()) {
std::cout << "GetObjectMeta fail" <<
",code:" << getObjectMetaResult.error().Code() <<
",message:" << getObjectMetaResult.error().Message() <<
",requestId:" << getObjectMetaResult.error().RequestId() << std::endl;
return -1;
}
/* Query the size of the source object. */
auto objectSize = getObjectMetaResult.result().ContentLength();
/* Copy the large object. */
InitiateMultipartUploadRequest initUploadRequest(CopyBucketName, CopyObjectName);
/* Initiate a multipart copy task. */
auto uploadIdResult = client.InitiateMultipartUpload(initUploadRequest);
auto uploadId = uploadIdResult.result().UploadId();
int64_t partSize = 100 * 1024;
PartList partETagList;
int partCount = static_cast<int>(objectSize / partSize);
/* Calculate the number of parts. */
if (objectSize % partSize != 0) {
partCount++;
}
/* Copy each part. */
for (int i = 1; i <= partCount; i++) {
auto skipBytes = partSize * (i - 1);
auto size = (partSize < objectSize - skipBytes) ? partSize : (objectSize - skipBytes);
auto uploadPartCopyReq = UploadPartCopyRequest(CopyBucketName, CopyObjectName, SourceBucketName, SourceObjectName,uploadId, i);
uploadPartCopyReq.setCopySourceRange(skipBytes, skipBytes + size -1);
auto uploadPartOutcome = client.UploadPartCopy(uploadPartCopyReq);
if (uploadPartOutcome.isSuccess()) {
Part part(i, uploadPartOutcome.result().ETag());
partETagList.push_back(part);
}
else {
std::cout << "UploadPartCopy fail" <<
",code:" << uploadPartOutcome.error().Code() <<
",message:" << uploadPartOutcome.error().Message() <<
",requestId:" << uploadPartOutcome.error().RequestId() << std::endl;
}
}
/* Complete the multipart copy task. */
CompleteMultipartUploadRequest request(CopyBucketName, CopyObjectName, partETagList, uploadId);
auto outcome = client.CompleteMultipartUpload(request);
if (!outcome.isSuccess()) {
/* Handle exceptions. */
std::cout << "CompleteMultipartUpload fail" <<
",code:" << outcome.error().Code() <<
",message:" << outcome.error().Message() <<
",requestId:" << outcome.error().RequestId() << std::endl;
return -1;
}
/* Release resources such as network resources. */
ShutdownSdk();
return 0;
}
References
For the complete sample code that is used to copy a large object and a small object, visit GitHub.
For more information about the API operation that you can call to copy a small object, see CopyObject.
For more information about the API operation that you can call to copy a large object, see UploadPartCopy.