拷贝文件
更新时间:2022-10-08
拷贝文件
拷贝一个文件
用户可以通过copy_object函数拷贝一个Object,如下代码所示:
Cpp
1void copyObject(Client& client, std::string destBucketName, std::string destKey, const std::string& srcBucketName, const std::string& srcKey) {
2
3 // 拷贝Object
4 int ret = client.copy_object(srcBucketName, srcKey, destBucketName, destKey, "STANDARD");//目标Object为标准存储
5}
CopyObjectResponse
对象中包含了新Object的ETag和修改时间。
用户也可以通过 CopyObjectRequest
实现Object的拷贝,如下代码所示:
Cpp
1// 初始化Client
2Client client = ...;
3
4// 创建CopyObjectRequest对象
5CopyObjectRequest copyObjectRequest(destBucketName, destKey, srcBucketName, srcKey);
6
7// 设置Metadata
8ObjectMetaData* userMetadata = copyObjectRequest.mutable_meta();
9userMetadata->set_user_meta("userMetaKey", "userMetaValue");
10
11// 复制Object
12CopyObjectResponse copyObjectResponse;
13int ret = client.copy_object(copyObjectRequest, ©ObjectResponse);
14
15std::cout << "ETag: " + copyObjectResponse.etag() <<
16 " LastModified: " << copyObjectResponse.last_modified());
同步Copy功能
当前BOS的CopyObject接口是通过同步方式实现的。同步方式下,BOS端会等待Copy实际完成才返回成功。同步Copy能帮助用户更准确的判断Copy状态,但用户感知的复制时间会变长,且复制时间和文件大小成正比。
同步Copy方式更符合业界常规,提升了与其它平台的兼容性。同步Copy方式还简化了BOS服务端的业务逻辑,提高了服务效率。
分块拷贝
除了通过CopyObject接⼝拷贝文件以外,BOS还提供了另外一种拷贝模式——Multipart Upload Copy。用户可以在如下的应用场景内(但不仅限于此),使用Multipart Upload Copy,如:
- 需要支持断点拷贝。
- 拷贝超过5GB大小的文件。
- 网络条件较差,和BOS的服务器之间的连接经常断开。
下面将介绍分步实现三步拷贝。
三步拷贝包含init、“拷贝分块”和complete三步,其中init和complete的操作同分块上传一致。
为了便于理解,下面提供三步拷贝完整代码:
Cpp
1// 第一步 init
2InitMultiUploadRequest initMultiUploadRequest("targetBucketName","targetObjectName");
3InitMultiUploadResponse initMultiUploadResponse;
4client.init_multipart_upload(initMultiUploadRequest, &initMultiUploadResponse);
5//获取Object大小
6HeadObjectRequest request("targetBucketName", "targetObjectName");
7HeadObjectResponse response;
8client.head_object(request, &response);
9if (response.is_fail()) {
10 return RET_SERVICE_ERROR;
11}
12long left_size = response.meta().content_length();
13
14// 第二步 分块拷贝
15long skipBytes = 0;
16int partNumber = 1;
17std::vector<part_t> partETags;
18
19while (left_size > 0) {
20 long partSize = 1024 * 1024 * 5L;
21 if (left_size < partSize) {
22 partSize = left_size;
23 }
24 CopyPartRequest copyPartRequest;
25 copyPartRequest.set_upload_id(initMultiUploadResponse.upload_id());
26 copyPartRequest.set_bucket_name("targetBucketName");
27 copyPartRequest.set_object_name("targetObjectName");
28 copyPartRequest.set_source_bucket_name("sourceBucketName");
29 copyPartRequest.set_source_object_name("sourceObjectName");
30 copyPartRequest.set_range(skipBytes, skipBytes + partSize - 1);
31 copyPartRequest.set_part_number(partNumber);
32
33 CopyPartResponse copyPartResponse;
34 client.copy_part(copyPartRequest, ©PartResponse);
35 // 将返回的partNumber和ETag保存到vector
36 part_t partInfo;
37 partInfo.etag = copyPartResponse.etag();
38 partInfo.part_number = partNumber;
39 partETags.push_back(partInfo);
40 left_size -= partSize;
41 skipBytes += partSize;
42 partNumber+=1;
43}
44
45// 第三步 complete
46CompleteMultipartUploadRequest completeMultipartUploadRequest("targetBucketName", "targetObjectName", initMultiUploadResponse.upload_id());
47
48//添加part信息,即part合并顺序
49for (part_t partInfo : partEtags) {
50 completeMultipartUploadRequest.add_part(partInfo.part_number, partInfo.etag);
51}
52
53// 完成分块上传
54CompleteMultipartUploadResponse completeMultipartUploadResponse;
55int ret = client.complete_multipart_upload(completeMultipartUploadRequest, &completeMultipartUploadResponse);
56
57// 打印Object的ETag
58std::cout << completeMultipartUploadResponse.etag() << std::endl;
注意:
- offset参数以字节为单位,为分块的开始偏移位置。
- size参数以字节为单位,定义每个分块的大小,除最后一个Part以外,其他的Part大小都要大于 5MB。
使用便利接口
parallel_copy
使用并发接口,提高请求吞吐,实现分块分块拷贝
C++
1client.parallel_copy(srcBucketName, sourceObjectName, destBucketName, destObjectName);