Copy files
For the sample code, please refer to File Copy Demo
Copy a file
Users can copy an object using the copyObject method, as shown in the following code:
1public void copyObject(BosClient client, String srcBucketName, String srcKey, String destBucketName, String destKey) {
2
3 // Copy Object
4 CopyObjectResponse copyObjectResponse = client.copyObject(srcBucketName, srcKey, destBucketName, destKey);
5
6 // Print results
7 System.out.println("ETag: " + copyObjectResponse.getETag() + " LastModified: " + copyObjectResponse.getLastModified());
8}
The copyObject method returns a CopyObjectResponse object containing the new object's ETag and modification time.
Copy Object via CopyObjectRequest
Users can also copy object via CopyObjectRequest. the code is as follows:
1// Initialize BosClient
2BosClient client = ...;
3
4 // Create CopyObjectRequest object
5CopyObjectRequest copyObjectRequest = new CopyObjectRequest(srcBucketName, srcKey, destBucketName, destKey);
6
7 // Set new Metadata
8Map<String, String> userMetadata = new HashMap<String, String>();
9userMetadata.put('<user-meta-key>','<user-meta-value>');
10ObjectMetadata meta = new ObjectMetadata();
11meta.setUserMetadata(userMetadata);
12copyObjectRequest.setNewObjectMetadata(meta);
13
14 // Copy Object
15CopyObjectResponse copyObjectResponse = client.copyObject(copyObjectRequest);
16
17System.out.println("ETag: " + copyObjectResponse.getETag() + " LastModified: " + copyObjectResponse.getLastModified());
CopyObjectRequest allows users to modify the ObjectMeta of the target object and also provides the setting of the MatchingETagConstraints parameter.
Set the copy attribute of the object
BOS provides a CopyObject API for copying an existing object to a different object. During the copying process, it evaluates the source object’s ETag or modification status to determine whether to proceed. Detailed parameter descriptions are as follows:
| Name | Types | Description | Whether required |
|---|---|---|---|
| x-bce-copy-source-if-match | String | If the ETag value of the source object matches the ETag value provided by the user, the copy operation is performed; otherwise, it fails. | No |
| x-bce-copy-source-if-none-match | String | If the ETag value of the source object does not match the ETag value provided by the user, the copy operation is performed; otherwise, it fails. | No |
| x-bce-copy-source-if-unmodified-since | String | If the source object has not been modified since x-bce-copy-source-if-unmodified-since, the copy operation will proceed; otherwise, it will fail. | No |
| x-bce-copy-source-if-modified-since | String | If the source object has been modified since x-bce-copy-source-if-modified-since, the copy operation will proceed; otherwise, it will fail. | No |
The corresponding example code:
1// Initialize BosClient
2BosClient client = ...;
3 // Create CopyObjectRequest object
4CopyObjectRequest copyObjectRequest = new CopyObjectRequest(srcBucketName, srcKey, destBucketName, destKey);
5 // Set new Metadata
6Map<String, String> userMetadata = new HashMap<String, String>();
7userMetadata.put("<user-meta-key>","<user-meta-value>");
8
9meta.setUserMetadata(userMetadata);
10copyObjectRequest.setNewObjectMetadata(meta);
11//copy-source-if-match
12copyObjectRequest.withETag("111111111183bf192b57a4afc76fa632");
13//copy-source-if-none-match
14copyObjectRequest.withNoMatchingETagConstraint("111111111183bf192b57a4afc76fa632");
15
16Date modifiedSinceConstraint = new Date();
17SimpleDateFormat df = new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss z", Locale.UK);
18df.setTimeZone(new java.util.SimpleTimeZone(0, "GMT"));
19String date = df.format(modifiedSinceConstraint);
20//copy-source-if-modified-since
21copyObjectRequest.withModifiedSinceConstraint(date);
22//copy-source-if-unmodified-since
23copyObjectRequest.withUnmodifiedSinceConstraint(date);
24 // Copy Object
25CopyObjectResponse copyObjectResponse = client.copyObject(copyObjectRequest);
26System.out.println("ETag: " + copyObjectResponse.getETag() + " LastModified: " + copyObjectResponse.getLastModified());
Synchronous copy function
Currently, BOS’s CopyObject API operates in a synchronous manner. This means BOS waits until the copy operation is fully completed before returning a success status. While synchronous copying provides a more accurate status for users, it also takes longer and is proportional to the file size.
The synchronous copy approach aligns better with industry standards and improves compatibility with other platforms. It also simplifies the server’s business logic and enhances service efficiency.
If you are using an SDK version earlier than bce-java-sdk-0.10.8, you might encounter scenarios where the copy request succeeds but the actual file copy fails. It is therefore recommended to use the latest version of the SDK.
Multipart copy
Apart from using the CopyObject API for copying, BOS offers another method—Multipart Upload Copy. This method is suitable for the following application scenarios (but not limited to these):
- When a resumable copy process is required.
- For copying files larger than 5GB.
- When the connection to the BOS server frequently disconnects due to poor network conditions.
The following section introduces the step-by-step process for implementing the three-step copy method.
The three-step copy process includes three stages: initialization ("init"), "copy part," and completion. The initialization and completion steps are the same as those for multipart uploads.
For easier understanding, the complete code for three-step copy is provided below:
1//Step I: init
2InitiateMultipartUploadRequest initiateMultipartUploadRequest =
3 new InitiateMultipartUploadRequest("targetBucketName","targetObjectName");
4InitiateMultipartUploadResponse initiateMultipartUploadResponse =
5 client.initiateMultipartUpload(initiateMultipartUploadRequest);
6 //Step II: Multipart copy
7long left_size=client.getObjectMetadata("sourceBucketName","sourceObjectName").getContentLength();
8long skipBytes = 0;
9int partNumber = 1;
10List<PartETag> partETags = new ArrayList<PartETag>();
11while (left_size > 0) {
12 long partSize = 1024 * 1024 * 1L;
13 if (left_size < partSize) {
14 partSize = left_size;
15 }
16 UploadPartCopyRequest uploadPartCopyRequest = new UploadPartCopyRequest();
17 uploadPartCopyRequest.setBucketName("targetBucketName");
18 uploadPartCopyRequest.setKey("targetObjectName");
19 uploadPartCopyRequest.setSourceBucketName("sourceBucketName");
20 uploadPartCopyRequest.setSourceKey("sourceObjectName");
21 uploadPartCopyRequest.setUploadId(initiateMultipartUploadResponse.getUploadId());
22 uploadPartCopyRequest.setPartSize(partSize);
23 uploadPartCopyRequest.setOffSet(skipBytes);
24 uploadPartCopyRequest.setPartNumber(partNumber);
25 UploadPartCopyResponse uploadPartCopyResponse = client.uploadPartCopy(uploadPartCopyRequest);
26 // Save the returned PartETag to the list
27 PartETag partETag = new PartETag(partNumber,uploadPartCopyResponse.getETag());
28 partETags.add(partETag);
29 left_size -= partSize;
30 skipBytes += partSize;
31 partNumber+=1;
32}
33 //Step III: complete
34CompleteMultipartUploadRequest completeMultipartUploadRequest =
35 new CompleteMultipartUploadRequest("targetBucketName", "targetObjectName", initiateMultipartUploadResponse.getUploadId(), partETags);
36CompleteMultipartUploadResponse completeMultipartUploadResponse =
37 client.completeMultipartUpload(completeMultipartUploadRequest);
Note:
- The offset parameter is specified in bytes and represents the starting position of the part within the file.
- The size parameter is in bytes and defines the size of each part. Except for the last part, the size of other Parts must be larger than 5MB。
