拷贝文件
示例代码可以参考拷贝文件Demo
拷贝一个文件
用户可以通过copyObject方法拷贝一个Object,如下代码所示:
1public void copyObject(BosClient client, String srcBucketName, String srcKey, String destBucketName, String destKey) {
2
3 // 拷贝Object
4 CopyObjectResponse copyObjectResponse = client.copyObject(srcBucketName, srcKey, destBucketName, destKey);
5
6 // 打印结果
7 System.out.println("ETag: " + copyObjectResponse.getETag() + " LastModified: " + copyObjectResponse.getLastModified());
8}
copyObject 方法返回一个 CopyObjectResponse
对象,该对象中包含了新Object的ETag和修改时间。
通过CopyObjectRequest拷贝Object
用户也可以通过 CopyObjectRequest
实现Object的拷贝,如下代码所示:
1// 初始化BosClient
2BosClient client = ...;
3
4// 创建CopyObjectRequest对象
5CopyObjectRequest copyObjectRequest = new CopyObjectRequest(srcBucketName, srcKey, destBucketName, destKey);
6
7// 设置新的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// 复制Object
15CopyObjectResponse copyObjectResponse = client.copyObject(copyObjectRequest);
16
17System.out.println("ETag: " + copyObjectResponse.getETag() + " LastModified: " + copyObjectResponse.getLastModified());
CopyObjectRequest
允许用户修改目的Object的ObjectMeta,同时也提供 MatchingETagConstraints
参数的设定。
设置Object的Copy属性
BOS同时会提供CopyObject接口用于将一个已经存在的Object拷贝到另外一个Object,拷贝过程中会对源Object的Etag或修改状态进行判断,根据判断结果决定是否执行拷贝。详细的参数解释如下:
名称 | 类型 | 描述 | 是否必需 |
---|---|---|---|
x-bce-copy-source-if-match | String | 如果源Object的ETag值和用户提供的ETag相等,则执行拷贝操作,否则拷贝失败。 | 否 |
x-bce-copy-source-if-none-match | String | 如果源Object的ETag和用户提供的ETag不相等,则执行拷贝操作,否则拷贝失败。 | 否 |
x-bce-copy-source-if-unmodified-since | String | 如果源object在x-bce-copy-source-if-unmodified-since之后没被修改,则执行拷贝操作,否则拷贝失败。 | 否 |
x-bce-copy-source-if-modified-since | String | 如果源object在x-bce-copy-source-if-modified-since之后被修改了,则执行拷贝操作,否则拷贝失败。 | 否 |
对应的示例代码:
1// 初始化BosClient
2BosClient client = ...;
3
4// 创建CopyObjectRequest对象
5CopyObjectRequest copyObjectRequest = new CopyObjectRequest(srcBucketName, srcKey, destBucketName, destKey);
6
7// 设置新的Metadata
8Map<String, String> userMetadata = new HashMap<String, String>();
9userMetadata.put("<user-meta-key>","<user-meta-value>");
10
11meta.setUserMetadata(userMetadata);
12copyObjectRequest.setNewObjectMetadata(meta);
13
14//copy-source-if-match
15copyObjectRequest.withETag("111111111183bf192b57a4afc76fa632");
16//copy-source-if-none-match
17copyObjectRequest.withNoMatchingETagConstraint("111111111183bf192b57a4afc76fa632");
18
19Date modifiedSinceConstraint = new Date();
20SimpleDateFormat df = new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss z", Locale.UK);
21df.setTimeZone(new java.util.SimpleTimeZone(0, "GMT"));
22String date = df.format(modifiedSinceConstraint);
23
24//copy-source-if-modified-since
25copyObjectRequest.withModifiedSinceConstraint(date);
26
27//copy-source-if-unmodified-since
28copyObjectRequest.withUnmodifiedSinceConstraint(date);
29
30// 复制Object
31CopyObjectResponse copyObjectResponse = client.copyObject(copyObjectRequest);
32
33System.out.println("ETag: " + copyObjectResponse.getETag() + " LastModified: " + copyObjectResponse.getLastModified());
同步Copy功能
当前BOS的CopyObject接口是通过同步方式实现的。同步方式下,BOS端会等待Copy实际完成才返回成功。同步Copy能帮助用户更准确的判断Copy状态,但用户感知的复制时间会变长,且复制时间和文件大小成正比。
同步Copy方式更符合业界常规,提升了与其它平台的兼容性。同步Copy方式还简化了BOS服务端的业务逻辑,提高了服务效率。
如果您使用bce-java-sdk-0.10.8版本之前的SDK,有可能会出现复制请求成功,但文件实际复制失败的情况,所以建议您使用最新版本SDK。
分块拷贝
除了通过CopyObject接⼝拷贝文件以外,BOS还提供了另外一种拷贝模式——Multipart Upload Copy。用户可以在如下的应用场景内(但不仅限于此),使用Multipart Upload Copy,如:
- 需要支持断点拷贝。
- 拷贝超过5GB大小的文件。
- 网络条件较差,和BOS的服务器之间的连接经常断开。
下面将介绍分步实现三步拷贝。
三步拷贝包含init、“拷贝分块”和complete三步,其中init和complete的操作同分块上传一致。
为了便于理解,下面提供三步拷贝完整代码:
1// 第一步 init
2InitiateMultipartUploadRequest initiateMultipartUploadRequest =
3 new InitiateMultipartUploadRequest("targetBucketName","targetObjectName");
4InitiateMultipartUploadResponse initiateMultipartUploadResponse =
5 client.initiateMultipartUpload(initiateMultipartUploadRequest);
6
7// 第二步 分块拷贝
8long left_size=client.getObjectMetadata("sourceBucketName","sourceObjectName").getContentLength();
9long skipBytes = 0;
10int partNumber = 1;
11List<PartETag> partETags = new ArrayList<PartETag>();
12
13while (left_size > 0) {
14 long partSize = 1024 * 1024 * 1L;
15 if (left_size < partSize) {
16 partSize = left_size;
17 }
18 UploadPartCopyRequest uploadPartCopyRequest = new UploadPartCopyRequest();
19 uploadPartCopyRequest.setBucketName("targetBucketName");
20 uploadPartCopyRequest.setKey("targetObjectName");
21 uploadPartCopyRequest.setSourceBucketName("sourceBucketName");
22 uploadPartCopyRequest.setSourceKey("sourceObjectName");
23 uploadPartCopyRequest.setUploadId(initiateMultipartUploadResponse.getUploadId());
24 uploadPartCopyRequest.setPartSize(partSize);
25 uploadPartCopyRequest.setOffSet(skipBytes);
26 uploadPartCopyRequest.setPartNumber(partNumber);
27 UploadPartCopyResponse uploadPartCopyResponse = client.uploadPartCopy(uploadPartCopyRequest);
28 // 将返回的PartETag保存到List中
29 PartETag partETag = new PartETag(partNumber,uploadPartCopyResponse.getETag());
30 partETags.add(partETag);
31 left_size -= partSize;
32 skipBytes += partSize;
33 partNumber+=1;
34}
35
36// 第三步 complete
37CompleteMultipartUploadRequest completeMultipartUploadRequest =
38 new CompleteMultipartUploadRequest("targetBucketName", "targetObjectName", initiateMultipartUploadResponse.getUploadId(), partETags);
39CompleteMultipartUploadResponse completeMultipartUploadResponse =
40 client.completeMultipartUpload(completeMultipartUploadRequest);
注意:
- offset参数以字节为单位,为分块的开始偏移位置。
- size参数以字节为单位,定义每个分块的大小,除最后一个Part以外,其他的Part大小都要大于 5MB。