This topic describes how to copy objects in a bucket with versioning enabled or suspended.

Copy small objects

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.
You can run the following code to copy objects smaller than 1 GB:
// This example uses the China East 1 (Hangzhou) endpoint. Specify the actual endpoint based on your requirements.
String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
// It is highly risky to log on with the AccessKey of an Alibaba Cloud account because the account has permissions on all the APIs in OSS. We recommend that you log on as a RAM user to access APIs or perform routine operations and maintenance. To create a RAM user account, log on to https://ram.console.aliyun.com.
String accessKeyId = "<yourAccessKeyId>";
String accessKeySecret = "<yourAccessKeySecret>";

// Creates an OSSClient instance.
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

String sourceBucketName = "<yourSourceBucketName>";
String sourceObjectName = "<yourSourceObjectName>";
String destinationBucketName = "<yourDestinationBucketName>";
String destinationObjectName = "<yourDestinationObjectName>";
String versionid = "<yourSourceObjectVersionid>";

CopyObjectRequest copyObjectRequest = new CopyObjectRequest(sourceBucketName, sourceObjectName, destinationBucketName, destinationObjectName);
copyObjectRequest.setSourceVersionId(versionid);
CopyObjectResult copyObjectResult = ossClient.copyObject(copyObjectRequest);
System.out.println("ETag: " + copyObjectResult.getETag() + " LastModified: " + copyObjectResult.getLastModified());
System.out.println("dest object versionid: " + copyObjectResult.getVersionId());

// Closes the OSSClient instance.
ossClient.shutdown();

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

Copy large objects

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.

You can run the following code to copy an object by using UploadPartCopy:
// This example uses the China East 1 (Hangzhou) endpoint. Specify the actual endpoint based on your requirements.
String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
// It is highly risky to log on with the AccessKey of an Alibaba Cloud account because the account has permissions on all the APIs in OSS. We recommend that you log on as a RAM user to access APIs or perform routine operations and maintenance. To create a RAM user account, log on to https://ram.console.aliyun.com.
String accessKeyId = "<yourAccessKeyId>";
String accessKeySecret = "<yourAccessKeySecret>";

String sourceBucketName = "<yourSourceBucketName>";
String sourceObjectName = "<yourSourceObjectName>";
String destinationBucketName = "<yourDestinationBucketName>";
String destinationObjectName = "<yourDestinationObjectName>";
String sourceObjectVersionid = "<yourSourceObjectVersionid>";

ObjectMetadata objectMetadata = ossClient.getObjectMetadata(sourceBucketName, sourceObjectName, sourceObjectVersionid);
// Obtains the size of the object to be copied.
long contentLength = objectMetadata.getContentLength();
// Sets the part size to 10 MB.
long partSize = 1024 * 1024 * 10;
// Calculates the number of parts.
int partCount = (int) (contentLength / partSize);
if (contentLength % partSize != 0) {
    partCount++;
}

System.out.println("total part count:" + partCount);
// Initializes a copy task. You can use InitiateMultipartUploadRequest to specify the metadata of the target object.
InitiateMultipartUploadRequest initiateMultipartUploadRequest = new InitiateMultipartUploadRequest(destinationBucketName, destinationObjectName);
InitiateMultipartUploadResult initiateMultipartUploadResult = ossClient.initiateMultipartUpload(initiateMultipartUploadRequest);
String uploadId = initiateMultipartUploadResult.getUploadId();

// Copies the parts.
List<PartETag> partETags = new ArrayList<PartETag>();
for (int i = 0; i < partCount; i++) {
     // Calculates the part size.
    long skipBytes = partSize * i;
    long size = partSize < contentLength - skipBytes ? partSize : contentLength - skipBytes;

    // Creates a request by using UploadPartCopyRequest.You can use UploadPartCopyRequest to specify conditions.
    UploadPartCopyRequest uploadPartCopyRequest =
        new UploadPartCopyRequest(sourceBucketName, sourceObjectName, destinationBucketName, destinationObjectName);
    uploadPartCopyRequest.setUploadId(uploadId);
    uploadPartCopyRequest.setPartSize(size);
    uploadPartCopyRequest.setBeginIndex(skipBytes);
    uploadPartCopyRequest.setPartNumber(i + 1);
    // Specifies the version ID of the source object.
    uploadPartCopyRequest.setSourceVersionId(sourceObjectVersionid);
    UploadPartCopyResult uploadPartCopyResult = ossClient.uploadPartCopy(uploadPartCopyRequest);

    // Stores the returned PartETags in partEtags.
    partETags.add(uploadPartCopyResult.getPartETag());
}

// Completes the UploadPartCopy task.
CompleteMultipartUploadRequest completeMultipartUploadRequest = new CompleteMultipartUploadRequest(
                    destinationBucketName, destinationObjectName, uploadId, partETags);
CompleteMultipartUploadResult completeMultipartUploadResult = ossClient.completeMultipartUpload(completeMultipartUploadRequest);
// Views the version ID of the target object.
System.out.println("object versionid: " + completeMultipartUploadResult.getVersionId());

// Closes the OSSClient instance.
ossClient.shutdown();

For more information about UploadPartCopy, see UploadPartCopy.