All Products
Search
Document Center

Object Storage Service:Copy objects

Last Updated:Mar 05, 2025

You can copy an object from a source Object Storage Service (OSS) on CloudBox bucket to a destination OSS on CloudBox bucket within the same region without modifying the content of the object. This object-copying feature enables data backup, distribution, and disaster recovery. By copying objects, you ensure data consistency and security across buckets while enhancing data availability and redundancy. CloudBox is an efficient and reliable data storage and management service provided by Alibaba Cloud.

Limits

  • Objects cannot be copied between OSS on CloudBox buckets located in different regions. For example, you cannot copy an object from a bucket in the China (Hangzhou) region to a bucket in the China (Shanghai) region.

  • Appendable objects cannot be copied.

Usage notes

  • You must have read permissions on the source object and read and write permissions on the destination bucket. Otherwise, the copy operation fails.

  • By default, when you copy an object that has the same name as an existing object in the destination path, the copied object overwrites the existing object in the destination path. You can use one of the following methods to protect your objects from being unexpectedly overwritten:

    • Enable versioning for the destination bucket

      If versioning is enabled for the destination bucket, overwritten objects are saved as previous versions. You can restore an object to a previous version at any time. For more information, see Versioning.

    • Include the x-oss-forbid-overwrite header in the copy request

      You can include the x-oss-forbid-overwrite header in the copy request and set the header to true to disable object overwriting. If you copy an object that has the same name as an existing object in the destination bucket, the object fails to be copied and the FileAlreadyExists error code is returned.

Copy a small object

OSS on CloudBox allows you to copy an object less than 1 GB in size by calling the CopyObject operation.

Use OSS SDK for Java

You can copy an object by using only OSS SDK for Java V3.15.0 or later. The following sample code copies a small object:

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.*;
import com.aliyun.oss.common.auth.DefaultCredentialProvider;
import com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.ClientBuilderConfiguration;
import com.aliyun.oss.common.auth.CredentialsProviderFactory;
import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;

public class Demo {
    public static void main(String[] args) throws Exception {
        // Specify the data endpoint of the OSS on CloudBox bucket. 
        String endpoint = "https://cb-f8z7yvzgwfkl9q0h****.cn-hangzhou.oss-cloudbox.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. 
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        // Specify the region in which the source and destination OSS on CloudBox buckets are located. 
        String region = "cn-hangzhou";
        // Specify the ID of the cloud box. 
        String cloudBoxId = "cb-f8z7yvzgwfkl9q0h****";
        // Specify the name of the source OSS on CloudBox bucket. 
        String sourceBucketName = "srcexamplebucket";
        // Specify the full path of the source object. Do not include the bucket name in the full path. 
        String sourceKey = "srcexampleobject.txt";
        // Specify the name of the destination OSS on CloudBox bucket that is located in the same region as the source OSS on CloudBox bucket. 
        String destinationBucketName = "desexamplebucket";
        // Specify the full path of the destination object. Do not include the bucket name in the full path. 
        String destinationKey = "desexampleobject.txt";

        // Create an OSSClient instance. 
        ClientBuilderConfiguration conf = new ClientBuilderConfiguration();
        conf.setSignatureVersion(SignVersion.V4);
        OSS ossClient = OSSClientBuilder.create()
                .endpoint(endpoint)
                .credentialsProvider(new DefaultCredentialProvider(credentialsProvider.getCredentials()))
                .clientConfiguration(conf)
                .region(region)
                .cloudBoxId(cloudBoxId)
                .build();

        try {
            // Create a CopyObjectRequest object. 
            CopyObjectRequest copyObjectRequest = new CopyObjectRequest(sourceBucketName, sourceKey, destinationBucketName, destinationKey);

            // Specify new object metadata. 
            ObjectMetadata meta = new ObjectMetadata();
            meta.setContentType("text/txt");
            // Specify whether the CopyObject operation overwrites an existing object that has the same name. In this example, this parameter is set to true, which specifies that the CopyObject operation does not overwrite an existing object that has the same name. 
            // meta.setHeader("x-oss-forbid-overwrite", "true");
            // Specify the path of the source object. 
            // meta.setHeader(OSSHeaders.COPY_OBJECT_SOURCE, "/examplebucket/recode-test.txt");
            // If the ETag value of the source object is the same as the ETag value that is specified in the request, OSS copies the object and returns 200 OK. 
            // meta.setHeader(OSSHeaders.COPY_OBJECT_SOURCE_IF_MATCH, "5B3C1A2E053D763E1B002CC607C5****");
            // If the ETag value of the source object is different from the ETag value that is specified in the request, OSS copies the object and returns 200 OK. 
            // meta.setHeader(OSSHeaders.COPY_OBJECT_SOURCE_IF_NONE_MATCH, "5B3C1A2E053D763E1B002CC607C5****");
            // If the time specified in the request is the same as or later than the modified time of the object, OSS copies the object and returns 200 OK. 
            // meta.setHeader(OSSHeaders.COPY_OBJECT_SOURCE_IF_UNMODIFIED_SINCE, "2021-12-09T07:01:56.000Z");
            // If the source object is modified after the time specified in the request, OSS copies the object. 
            // meta.setHeader(OSSHeaders.COPY_OBJECT_SOURCE_IF_MODIFIED_SINCE, "2021-12-09T07:01:56.000Z");
            // Specify the method that is used to configure the metadata of the destination object. In this example, the method is set to COPY, which specifies that the metadata of the source object is copied to the destination object. 
            // meta.setHeader(OSSHeaders.COPY_OBJECT_METADATA_DIRECTIVE, "COPY");
            // Specify the server-side encryption algorithm that is used to encrypt the destination object when the object is created. 
            // meta.setHeader(OSSHeaders.OSS_SERVER_SIDE_ENCRYPTION, ObjectMetadata.KMS_SERVER_SIDE_ENCRYPTION);
            // Specify the customer master key (CMK) that is managed by Key Management Service (KMS). This parameter takes effect only when you set x-oss-server-side-encryption to KMS. 
            // meta.setHeader(OSSHeaders.OSS_SERVER_SIDE_ENCRYPTION_KEY_ID, "9468da86-3509-4f8d-a61e-6eab1eac****");
            // Specify the access control list (ACL) of the destination object. In this example, the ACL is set to private, which specifies that only the object owner and authorized users have the read and write permissions on the object. 
            // meta.setHeader(OSSHeaders.OSS_OBJECT_ACL, CannedAccessControlList.Private);
            // Specify the storage class of the destination object. In this example, the storage class is set to Standard. 
            // meta.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard);
            // Specify one or more tags for the destination object. 
            // meta.setHeader(OSSHeaders.OSS_TAGGING, "a:1");
            // Specify the method that is used to configure tags for the destination object. In this example, the method is set to COPY, which specifies that the tags of the source object are copied to the destination object. 
            // meta.setHeader(OSSHeaders.COPY_OBJECT_TAGGING_DIRECTIVE, "COPY");
            copyObjectRequest.setNewObjectMetadata(meta);

            // Copy the object. 
            CopyObjectResult result = ossClient.copyObject(copyObjectRequest);
            System.out.println("ETag: " + result.getETag() + " LastModified: " + result.getLastModified());
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }
}

Use ossutil

You can use ossutil to copy an object less than 1 GB in size. For more information, see Copy objects.

Copy a large object

OSS on CloudBox allows you to copy an object greater than 1 GB in size by calling the UploadPartCopy operation.

Use OSS SDK for Java

You can copy an object by using only OSS SDK for Java V3.15.0 or later. The following sample code copies a large object:

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.*;
import java.util.ArrayList;
import java.util.List;
import com.aliyun.oss.common.auth.DefaultCredentialProvider;
import com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.ClientBuilderConfiguration;
import com.aliyun.oss.common.auth.CredentialsProviderFactory;
import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;

public class Demo {
    public static void main(String[] args) throws Exception {
        // Specify the data endpoint of the OSS on CloudBox bucket. 
        String endpoint = "https://cb-f8z7yvzgwfkl9q0h****.cn-hangzhou.oss-cloudbox.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. 
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        // Specify the region in which the source and destination OSS on CloudBox buckets are located. 
        String region = "cn-hangzhou";
        // Specify the ID of the cloud box. 
        String cloudBoxId = "cb-f8z7yvzgwfkl9q0h****";
        // Specify the name of the source OSS on CloudBox bucket. 
        String sourceBucketName = "srcexamplebucket";
        // Specify the full path of the source object. Do not include the bucket name in the full path. 
        String sourceKey = "srcexampleobject.txt";
        // Specify the name of the destination OSS on CloudBox bucket that is located in the same region as the source OSS on CloudBox bucket. 
        String destinationBucketName = "desexamplebucket";
        // Specify the full path of the destination object. Do not include the bucket name in the full path. 
        String destinationKey = "desexampleobject.txt";

        // Create an OSSClient instance. 
        ClientBuilderConfiguration conf = new ClientBuilderConfiguration();
        conf.setSignatureVersion(SignVersion.V4);
        OSS ossClient = OSSClientBuilder.create()
                .endpoint(endpoint)
                .credentialsProvider(new DefaultCredentialProvider(credentialsProvider.getCredentials()))
                .clientConfiguration(conf)
                .region(region)
                .cloudBoxId(cloudBoxId)
                .build();

        try {
            ObjectMetadata objectMetadata = ossClient.getObjectMetadata(sourceBucketName, sourceKey);
            // Query the size of the source object. 
            long contentLength = objectMetadata.getContentLength();

            // Set the part size in bytes. In this example, the part size is set to 10 MB.  
            long partSize = 1024 * 1024 * 10;

            // Calculate the total number of parts. 
            int partCount = (int) (contentLength / partSize);
            if (contentLength % partSize != 0) {
                partCount++;
            }
            System.out.println("total part count:" + partCount);

            // Initiate a multipart copy task. Specify the metadata of the destination object by using InitiateMultipartUploadRequest. 
            InitiateMultipartUploadRequest initiateMultipartUploadRequest = new InitiateMultipartUploadRequest(destinationBucketName, destinationKey);
            InitiateMultipartUploadResult initiateMultipartUploadResult = ossClient.initiateMultipartUpload(initiateMultipartUploadRequest);
            String uploadId = initiateMultipartUploadResult.getUploadId();

            // Start the multipart copy task. 
            List<PartETag> partETags = new ArrayList<PartETag>();
            for (int i = 0; i < partCount; i++) {
                // Calculate the part size. 
                long skipBytes = partSize * i;
                long size = partSize < contentLength - skipBytes ?  partSize : contentLength - skipBytes;

                // Create an UploadPartCopyRequest object. You can specify conditions by using UploadPartCopyRequest. 
                UploadPartCopyRequest uploadPartCopyRequest =
                        new UploadPartCopyRequest(sourceBucketName, sourceKey, destinationBucketName, destinationKey);
                uploadPartCopyRequest.setUploadId(uploadId);
                uploadPartCopyRequest.setPartSize(size);
                uploadPartCopyRequest.setBeginIndex(skipBytes);
                uploadPartCopyRequest.setPartNumber(i + 1);
                UploadPartCopyResult uploadPartCopyResult = ossClient.uploadPartCopy(uploadPartCopyRequest);

                // Store the returned part ETags in partETags. 
                partETags.add(uploadPartCopyResult.getPartETag());
            }

            // Complete the multipart copy task. 
            CompleteMultipartUploadRequest completeMultipartUploadRequest = new CompleteMultipartUploadRequest(
                    destinationBucketName, destinationKey, uploadId, partETags);
            ossClient.completeMultipartUpload(completeMultipartUploadRequest);
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }
}     

Use ossutil

You can use ossutil to copy an object larger than 1 GB in size. For more information, see Copy objects.

Use the OSS API

If your business requires a high level of customization, you can directly call RESTful APIs. To directly call an API, you must include the signature calculation in your code. For more information, see UploadPartCopy.