This topic describes how to copy objects from a versioning-enabled bucket.

Copy a small object

You can use the CopyObject method to copy an object smaller than 1 GB from a bucket (source bucket) to another bucket (target bucket) in the same region.

Note
  • CopyObject copies the current version of an object by default. If the current version of the target object is a delete marker, the 404 Not Found error is returned to indicate that the object does not exist. You can specify the versionId in a CopyObject request to copy a specified version of the target object. However, a delete marker cannot be copied
  • You can copy a historical version of an object to the bucket that stores the object. The copied historical version becomes the current version of a new object. You can use this method to restore a historical version of an object.
  • If versioning is enabled for the bucket that stores the target object, OSS generates a unique version ID for the copied object, which is returned in the x-oss-version-id field in the response header. If versioning is suspended or not enabled for the bucket that stores the target object, OSS generates a version of which the ID is null for the copied object and overwrite overwrites the original version of which the ID is null.
  • If versioning is enabled or suspended for a bucket, you cannot perform the CopyObject operation on appendable objects in the bucket.

The following code provides an example on how to copy objects smaller than 1 GB:

#include <alibabacloud/oss/OssClient.h>
using namespace AlibabaCloud::OSS;

int main(void)
{
    /*Initialize the OSS account information.*/
    std::string AccessKeyId = "yourAccessKeyId";
    std::string AccessKeySecret = "yourAccessKeySecret";
    std::string Endpoint = "yourEndpoint";
    std::string SourceBucketName = "yourSourceBucketName";
    std::string CopyBucketName = "yourCopyBucketName";
    std::string SourceObjectName = "yourSourceObjectName";
    std::string CopyObjectName = "yourCopyObjectName";

    /*Initialize network resources.*/
    InitializeSdk();

    ClientConfiguration conf;
    OssClient client(Endpoint, AccessKeyId, AccessKeySecret, conf);

    CopyObjectRequest request(CopyBucketName, CopyObjectName);
    request.setCopySource(SourceBucketName, SourceObjectName);
    request.setVersionId("yourSourceObjectVersionId");

    /*Copy an object with a specified version ID.*/
    auto outcome = client.CopyObject(request);

    if (outcome.isSuccess()) {
        std::cout << "versionid:" << outcome.result().VersionId() << std::endl;
    }
    else {
        /*Handle exceptions.*/
        std::cout << "CopyObject fail" <<
        ",code:" << outcome.error().Code() <<
        ",message:" << outcome.error().Message() <<
        ",requestId:" << outcome.error().RequestId() << std::endl;
        ShutdownSdk();
        return -1;
    }

    /*Release network resources.*/
    ShutdownSdk();
    return 0;
}

For more information about copying objects smaller than 1 GB, see CopyObject.

Copy a large object

To copy an object larger than 1 GB, you must use UploadPartCopy.

By default, UploadPartCopy uploads a part by copying the data from the current version of an existing object. You can add the versionId in the request header x-oss-copy-source as the condition to upload a part by copying the data from a specified version of an existing object. For example, x-oss-copy-source : /SourceBucketName/SourceObjectName?versionId=111111.
Note The SourceObjectName, which is a URL, must be encoded. The version ID of the copied object is returned as the x-oss-copy-source-version-id field in the response.

If you do not specify the versionId in the request header and the current version of the object to be copied is a delete marker, the 404 Not Found error is returned. If you specify the versionId in the request header and the specified version of the object is a delete marker, the 400 Bad Request error is returned.

The following code provides an example for multipart copy:

#include <alibabacloud/oss/OssClient.h>
#include <sstream>
using namespace AlibabaCloud::OSS;

int main(void)
{
    /*Initialize the OSS account information.*/
    std::string AccessKeyId = "yourAccessKeyId";
    std::string AccessKeySecret = "yourAccessKeySecret";
    std::string Endpoint = "yourEndpoint";
    std::string SourceBucketName = "yourSourceBucketName";
    std::string CopyBucketName = "yourCopyBucketName";
    std::string SourceObjectName = "yourSourceObjectName";
    std::string CopyObjectName = "yourCopyObjectName";

    /*Initialize network resources.*/
    InitializeSdk();

    ClientConfiguration conf;
    OssClient client(Endpoint, AccessKeyId, AccessKeySecret, conf);

    auto getObjectMetaReq = GetObjectMetaRequest(SourceBucketName, SourceObjectName);
    getObjectMetaReq.setVersionId("yourSourceObjectVersionid");
    auto getObjectMetaResult = GetObjectMeta(getObjectMetaReq);
    if (! getObjectMetaResult.isSuccess()) {
        std::cout << "GetObjectMeta fail" <<
        ",code:" << outcome.error().Code() <<
        ",message:" << outcome.error().Message() <<
        ",requestId:" << outcome.error().RequestId() << std::endl;
        ShutdownSdk();
        return -1;
    }
    /*Obtain the size of the object you want to copy.*/
    auto objectSize = getObjectMetaResult.result().ContentLength();

    /*Copy the large object.*/
    InitiateMultipartUploadRequest initUploadRequest(BucketName, ObjectName, metaData);

    /*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 sequentially.*/
    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 + 1);
        uploadPartCopyReq.setCopySourceRange(skipBytes, skipBytes + size -1);
        uploadPartCopyReq.setVersionId("yourSourceObjectVersionid");
        auto uploadPartOutcome = client.UploadPartCopy(uploadPartCopyReq);
        if (uploadPartOutcome.isSuccess()) {
            Part part(i, uploadPartOutcome.result().ETag());
            partETagList.push_back(part);
        }
        else {
            std::cout << "UploadPartCopy fail" <<
            ",code:" << outcome.error().Code() <<
            ",message:" << outcome.error().Message() <<
            ",requestId:" << outcome.error().RequestId() << std::endl;
        }
    }

    /*Complete multipart copy.*/
    CompleteMultipartUploadRequest request(CopyBucketName, CopyObjectName, partETagList, uploadId);
    auto outcome = client.CompleteMultipartUpload(request);

    if (outcome.isSuccess()) {
        std::cout << "versionid:" << outcome.result().VersionId() << std::endl;
    }
    else {
        /*Handle exceptions.*/
        std::cout << "CompleteMultipartUpload fail" <<
        ",code:" << outcome.error().Code() <<
        ",message:" << outcome.error().Message() <<
        ",requestId:" << outcome.error().RequestId() << std::endl;
        ShutdownSdk();
        return -1;
    }

    /*Release network resources.*/
    ShutdownSdk();
    return 0;
}

For more information about UploadPartCopy, see UploadPartCopy.