拷贝文件
更新时间:2022-10-08
拷贝文件
拷贝一个文件
用户可以通过copy_object函数拷贝一个Object,如下代码所示:
void copyObject(Client& client, std::string destBucketName, std::string destKey, const std::string& srcBucketName, const std::string& srcKey) {
// 拷贝Object
int ret = client.copy_object(srcBucketName, srcKey, destBucketName, destKey, "STANDARD");//目标Object为标准存储
}
CopyObjectResponse
对象中包含了新Object的ETag和修改时间。
用户也可以通过 CopyObjectRequest
实现Object的拷贝,如下代码所示:
// 初始化Client
Client client = ...;
// 创建CopyObjectRequest对象
CopyObjectRequest copyObjectRequest(destBucketName, destKey, srcBucketName, srcKey);
// 设置Metadata
ObjectMetaData* userMetadata = copyObjectRequest.mutable_meta();
userMetadata->set_user_meta("userMetaKey", "userMetaValue");
// 复制Object
CopyObjectResponse copyObjectResponse;
int ret = client.copy_object(copyObjectRequest, ©ObjectResponse);
std::cout << "ETag: " + copyObjectResponse.etag() <<
" 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的操作同分块上传一致。
为了便于理解,下面提供三步拷贝完整代码:
// 第一步 init
InitMultiUploadRequest initMultiUploadRequest("targetBucketName","targetObjectName");
InitMultiUploadResponse initMultiUploadResponse;
client.init_multipart_upload(initMultiUploadRequest, &initMultiUploadResponse);
//获取Object大小
HeadObjectRequest request("targetBucketName", "targetObjectName");
HeadObjectResponse response;
client.head_object(request, &response);
if (response.is_fail()) {
return RET_SERVICE_ERROR;
}
long left_size = response.meta().content_length();
// 第二步 分块拷贝
long skipBytes = 0;
int partNumber = 1;
std::vector<part_t> partETags;
while (left_size > 0) {
long partSize = 1024 * 1024 * 5L;
if (left_size < partSize) {
partSize = left_size;
}
CopyPartRequest copyPartRequest;
copyPartRequest.set_upload_id(initMultiUploadResponse.upload_id());
copyPartRequest.set_bucket_name("targetBucketName");
copyPartRequest.set_object_name("targetObjectName");
copyPartRequest.set_source_bucket_name("sourceBucketName");
copyPartRequest.set_source_object_name("sourceObjectName");
copyPartRequest.set_range(skipBytes, skipBytes + partSize - 1);
copyPartRequest.set_part_number(partNumber);
CopyPartResponse copyPartResponse;
client.copy_part(copyPartRequest, ©PartResponse);
// 将返回的partNumber和ETag保存到vector
part_t partInfo;
partInfo.etag = copyPartResponse.etag();
partInfo.part_number = partNumber;
partETags.push_back(partInfo);
left_size -= partSize;
skipBytes += partSize;
partNumber+=1;
}
// 第三步 complete
CompleteMultipartUploadRequest completeMultipartUploadRequest("targetBucketName", "targetObjectName", initMultiUploadResponse.upload_id());
//添加part信息,即part合并顺序
for (part_t partInfo : partEtags) {
completeMultipartUploadRequest.add_part(partInfo.part_number, partInfo.etag);
}
// 完成分块上传
CompleteMultipartUploadResponse completeMultipartUploadResponse;
int ret = client.complete_multipart_upload(completeMultipartUploadRequest, &completeMultipartUploadResponse);
// 打印Object的ETag
std::cout << completeMultipartUploadResponse.etag() << std::endl;
注意:
- offset参数以字节为单位,为分块的开始偏移位置。
- size参数以字节为单位,定义每个分块的大小,除最后一个Part以外,其他的Part大小都要大于 5MB。
使用便利接口
parallel_copy
使用并发接口,提高请求吞吐,实现分块分块拷贝
client.parallel_copy(srcBucketName, sourceObjectName, destBucketName, destObjectName);