All Products
Search
Document Center

Object Storage Service:Copy objects

Last Updated:Dec 06, 2023

This topic describes how to copy an object in a versioned bucket. You can call CopyObject to copy an object that is up to 1 GB in size and call UploadPartCopy to copy an object that is larger than 1 GB in size by using multipart copy.

Usage notes

  • In this topic, the public endpoint of the China (Hangzhou) region is used. If you want to access Object Storage Service (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 Create an OSSClient instance.

  • To copy an object, you must have the oss:GetObject and oss:PutObject permissions. For more information, see Attach a custom policy to a RAM user.

Copy a small object

You can call CopyObject to copy an object that is up to 1 GB in size from a source bucket to a destination bucket within the same region.

  • By default, the x-oss-copy-source header specifies the current version of the object to copy. If the current version of the object is a delete marker, OSS returns HTTP status code 404. The HTTP status code indicates that the object does not exist. You can add a version ID to the x-oss-copy-source header to copy a specified object version. Delete markers cannot be copied.

  • You can copy a previous version of an object to the same bucket. The copied previous version becomes the new version of the object. This way, the previous version of the object is recovered.

  • If versioning is enabled for the destination bucket, OSS generates a unique version ID for the destination object. The version ID is returned in the response as the x-oss-version-id header value. If versioning is disabled or suspended for the destination bucket, OSS generates a version whose version ID is null for the destination object and overwrites the original version whose version ID is null.

  • Appendable objects cannot be copied to a destination bucket for which versioning is enabled or suspended.

The following sample 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 = "https://oss-cn-hangzhou.aliyuncs.com";
    /* 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;
    /* 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);

    CopyObjectRequest request(CopyBucketName, CopyObjectName);
    request.setCopySource(SourceBucketName, SourceObjectName);
    /* Specify the version ID of the source object. */
    request.setVersionId("yourSourceObjectVersionId");

    /* Copy the specified version of the source object. */
    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;
        return -1;
    }

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

Copy a large object

To copy an object that is larger than 1 GB in size, you need to split the object into parts and copy the parts by using UploadPartCopy.

By default, the UploadPartCopy operation uploads a part by copying data from the current version of the specified object. You can add a version ID to the x-oss-copy-source header to copy the specified version of the object. Example: x-oss-copy-source: /SourceBucketName/SourceObjectName?versionId=CAEQMxiBgICAof2D0BYiIDJhMGE3N2M1YTI1NDQzOGY5NTkyNTI3MGYyMzJm****.

Note

The value of the SourceObjectName parameter must be URL-encoded. The version ID of the copied object is returned as the value of the x-oss-copy-source-version-id header in the response.

If a version ID is not specified in the request and the current version of the source object is a delete marker, OSS returns 404 Not Found. If a version ID is specified in the request and the specified version of the source object is a delete marker, OSS returns 400 Bad Request.

The following sample code provides an example on how to copy a large object by using multipart copy:

#include <alibabacloud/oss/OssClient.h>
#include <sstream>
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 = "https://oss-cn-hangzhou.aliyuncs.com";
    /* 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;
    /* 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);

    auto getObjectMetaReq = GetObjectMetaRequest(SourceBucketName, SourceObjectName);
    /* Specify the version ID of the source object. */
    getObjectMetaReq.setVersionId("yourSourceObjectVersionId");
    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 object that you want to copy. */
    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);
        /* Specify the version ID of the source object. */
        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:" << 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()) {
        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;
        return -1;
    }

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

References

  • 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.