This topic describes how to copy an object in a versioning-enabled bucket. To copy an object that is smaller than 1 GB, use the CopyObject method. To copy an object that is larger than 1 GB, use the UploadPartCopy method.
Usage notes
In this topic, the public endpoint of the China (Hangzhou) region is used. To access OSS from other Alibaba Cloud services in the same region, use an internal endpoint. For details about supported regions and endpoints, see OSS regions and endpoints.
In this topic, access credentials are obtained from environment variables. For more information about how to configure access credentials, see Configure access credentials.
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 Configuration examples for common scenarios.
To copy an object, you must have the
oss:GetObjectandoss:PutObjectpermissions. For more information, see Attach a custom policy to a RAM user.
Copy a small object
To copy an object that is smaller than 1 GB from a source bucket to a destination bucket in the same region, call the CopyObject method.
By default, x-oss-copy-source copies the current version of the object. If the current version is a delete marker, OSS returns a 404 Not Found error. To copy a specific version of an object, include the version ID in the x-oss-copy-source header. You cannot copy delete markers.
You can copy a previous version of an object to the same bucket. The copied version becomes the new current version of the object, which restores the previous version.
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 x-oss-version-id response header. If versioning is disabled or suspended for the destination bucket, OSS generates a version with a null version ID for the destination object and overwrites the existing version that also has a null version ID.
Appendable objects cannot be copied to a destination bucket for which versioning is enabled or suspended.
The following code shows how to copy a small object:
import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.model.*;
public class Demo {
public static void main(String[] args) throws Exception {
// In this example, the endpoint for the China (Hangzhou) region is used. Specify your actual endpoint.
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// Obtain access credentials from environment variables. Before you run this code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured.
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// Specify the name of the source bucket.
String sourceBucketName = "srcexamplebucket";
// Specify the full path of the source object. Do not include the bucket name in the full path.
String sourceObjectName = "srcexampleobject.txt";
// Specify the name of the destination bucket. The destination bucket must be in the same region as the source bucket.
String destinationBucketName = "desexamplebucket";
// Specify the full path of the destination object. Do not include the bucket name in the full path.
String destinationObjectName = "desexampleobject.txt";
String versionId = "CAEQMxiBgICAof2D0BYiIDJhMGE3N2M1YTI1NDQzOGY5NTkyNTI3MGYyMzJm****";
// Specify the region where the bucket is located. For example, if the bucket is in the China (Hangzhou) region, set the region to cn-hangzhou.
String region = "cn-hangzhou";
// Create an OSSClient instance.
// When the OSSClient instance is no longer needed, call the shutdown method to release its resources.
ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
OSS ossClient = OSSClientBuilder.create()
.endpoint(endpoint)
.credentialsProvider(credentialsProvider)
.clientConfiguration(clientBuilderConfiguration)
.region(region)
.build();
try {
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());
} 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();
}
}
}
}Copy a large object
For objects that are larger than 1 GB, use multipart copy (UploadPartCopy).
By default, the UploadPartCopy operation uploads a part by copying data from the current version of a source object. You can copy data from a specific version of an object by including the versionId subresource in the x-oss-copy-source request header. For example: x-oss-copy-source: /SourceBucketName/SourceObjectName?versionId=111111.
The value of SourceObjectName must be URL-encoded. The response returns the version ID of the source object in the x-oss-copy-source-version-id header.
If you do not specify a version ID and the current version of the source object is a delete marker, OSS returns a 404 Not Found error. If you specify the version ID of a delete marker, OSS returns a 400 Bad Request error.
The following code shows how to perform a multipart copy:
import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.model.*;
import java.util.ArrayList;
import java.util.List;
public class Demo {
public static void main(String[] args) throws Exception {
// In this example, the endpoint for the China (Hangzhou) region is used. Specify your actual endpoint.
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// Obtain access credentials from environment variables. Before you run this code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured.
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// Specify the name of the source bucket.
String sourceBucketName = "srcexamplebucket";
// Specify the full path of the source object. Do not include the bucket name in the full path.
String sourceObjectName = "srcexampleobject.txt";
// Specify the name of the destination bucket. The destination bucket must be in the same region as the source bucket.
String destinationBucketName = "desexamplebucket";
// Specify the full path of the destination object. Do not include the bucket name in the full path.
String destinationObjectName = "desexampleobject.txt";
String sourceObjectVersionId = "CAEQMxiBgICAof2D0BYiIDJhMGE3N2M1YTI1NDQzOGY5NTkyNTI3MGYyMzJm****";
// Specify the region where the bucket is located. For example, if the bucket is in the China (Hangzhou) region, set the region to cn-hangzhou.
String region = "cn-hangzhou";
// Create an OSSClient instance.
// When the OSSClient instance is no longer needed, call the shutdown method to release its resources.
ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
OSS ossClient = OSSClientBuilder.create()
.endpoint(endpoint)
.credentialsProvider(credentialsProvider)
.clientConfiguration(clientBuilderConfiguration)
.region(region)
.build();
try {
ObjectMetadata objectMetadata = ossClient.getObjectMetadata(sourceBucketName, sourceObjectName);
// Get the size of the object to copy.
long contentLength = objectMetadata.getContentLength();
// Set the part size 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);
// Initialize the multipart copy. You can specify the metadata of the destination object in InitiateMultipartUploadRequest.
InitiateMultipartUploadRequest initiateMultipartUploadRequest = new InitiateMultipartUploadRequest(destinationBucketName, destinationObjectName);
InitiateMultipartUploadResult initiateMultipartUploadResult = ossClient.initiateMultipartUpload(initiateMultipartUploadRequest);
String uploadId = initiateMultipartUploadResult.getUploadId();
// Copy the object in parts.
List<PartETag> partETags = new ArrayList<PartETag>();
for (int i = 0; i < partCount; i++) {
// Calculate the size of each part.
long skipBytes = partSize * i;
long size = partSize < contentLength - skipBytes ? partSize : contentLength - skipBytes;
// Create an UploadPartCopyRequest. You can specify conditions in the request.
UploadPartCopyRequest uploadPartCopyRequest =
new UploadPartCopyRequest(sourceBucketName, sourceObjectName, destinationBucketName, destinationObjectName);
uploadPartCopyRequest.setUploadId(uploadId);
uploadPartCopyRequest.setPartSize(size);
uploadPartCopyRequest.setBeginIndex(skipBytes);
uploadPartCopyRequest.setPartNumber(i + 1);
// Specify the version ID of the source object.
uploadPartCopyRequest.setSourceVersionId(sourceObjectVersionId);
UploadPartCopyResult uploadPartCopyResult = ossClient.uploadPartCopy(uploadPartCopyRequest);
// Save the returned part ETags in partETags.
partETags.add(uploadPartCopyResult.getPartETag());
}
// Complete the multipart copy.
CompleteMultipartUploadRequest completeMultipartUploadRequest = new CompleteMultipartUploadRequest(
destinationBucketName, destinationObjectName, uploadId, partETags);
CompleteMultipartUploadResult completeMultipartUploadResult = ossClient.completeMultipartUpload(completeMultipartUploadRequest);
// View the version ID of the destination object.
System.out.println("object versionid: " + completeMultipartUploadResult.getVersionId());
} 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();
}
}
}
}References
For more information about the API operation used to copy small objects, see CopyObject.
For more information about the API operation used to copy large objects, see UploadPartCopy.