本文介紹如何將源Bucket中的文件(Object)復制到同一地域下相同或不同目標Bucket中。
注意事項
本文以華東1(杭州)外網Endpoint為例。如果您希望通過與OSS同地域的其他阿里云產品訪問OSS,請使用內網Endpoint。關于OSS支持的Region與Endpoint的對應關系,請參見OSS地域和訪問域名。
本文以OSS域名新建OSSClient為例。如果您希望通過自定義域名、STS等方式新建OSSClient,請參見新建OssClient。
拷貝文件時,您必須擁有源文件的讀權限及目標Bucket的讀寫權限。
拷貝文件時,您需要確保源Bucket和目標Bucket均未設置合規保留策略,否則報錯The object you specified is immutable.。
不支持跨地域拷貝。例如不能將華東1(杭州)地域存儲空間中的文件拷貝到華北1(青島)地域。
拷貝小文件
對于小于1GB 的文件,您可以通過client.CopyObject方法將文件從一個存儲空間(源存儲空間)復制到同一地域的另一個存儲空間(目標存儲空間)。該方法的參數指定方式說明如下:
參數指定方式 | 描述 |
CopyObjectOutcome OssClient::CopyObject(const CopyObjectRequest &request) | 允許指定目標文件的元數據和拷貝的限制條件。如果拷貝操作的源文件地址和目標文件地址相同,則直接替換源文件的元數據。 |
以下代碼用于拷貝小文件:
#include <alibabacloud/oss/OssClient.h>
using namespace AlibabaCloud::OSS;
int main(void)
{
/* 初始化OSS賬號信息。*/
/* yourEndpoint填寫Bucket所在地域對應的Endpoint。以華東1(杭州)為例,Endpoint填寫為https://oss-cn-hangzhou.aliyuncs.com。*/
std::string Endpoint = "yourEndpoint";
/* yourRegion填寫Bucket所在地域對應的Region。以華東1(杭州)為例,Region填寫為cn-hangzhou。*/
std::string Region = "yourRegion";
/* 填寫源Bucket名稱,例如srcexamplebucket。*/
std::string SourceBucketName = "srcexamplebucket";
/* 填寫與源Bucket處于同一地域的目標Bucket名稱,例如destbucket。*/
std::string CopyBucketName = "destbucket";
/* 填寫源Object的完整路徑,完整路徑中不能包含Bucket名稱,例如srcdir/scrobject.txt。*/
std::string SourceObjectName = "srcdir/scrobject.txt";
/* 填寫目標Object的完整路徑,完整路徑中不能包含Bucket名稱,例如destdir/destobject.txt。*/
std::string CopyObjectName = "destdir/destobject.txt";
/* 初始化網絡等資源。*/
InitializeSdk();
ClientConfiguration conf;
conf.signatureVersion = SignatureVersionType::V4;
/* 從環境變量中獲取訪問憑證。運行本代碼示例之前,請確保已設置環境變量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。*/
auto credentialsProvider = std::make_shared<EnvironmentVariableCredentialsProvider>();
OssClient client(Endpoint, credentialsProvider, conf);
client.SetRegion(Region);
CopyObjectRequest request(CopyBucketName, CopyObjectName);
request.setCopySource(SourceBucketName, SourceObjectName);
/* 拷貝文件。*/
auto outcome = client.CopyObject(request);
if (!outcome.isSuccess()) {
/* 異常處理。*/
std::cout << "CopyObject fail" <<
",code:" << outcome.error().Code() <<
",message:" << outcome.error().Message() <<
",requestId:" << outcome.error().RequestId() << std::endl;
return -1;
}
/* 釋放網絡等資源。*/
ShutdownSdk();
return 0;
}
拷貝大文件
對于大于1 GB的文件,需要使用分片拷貝(UploadPartCopy)。分片拷貝分為三步:
通過client.InitiateMultipartUpload初始化分片拷貝任務。
通過client.UploadPartCopy進行分片拷貝。除最后一個分片外,其它分片都要大于100 KB。
通過client.CompleteMultipartUpload提交分片拷貝任務。
以下代碼用于拷貝大文件:
#include <alibabacloud/oss/OssClient.h>
using namespace AlibabaCloud::OSS;
int main(void)
{
/* 初始化OSS賬號信息 */
/* yourEndpoint填寫Bucket所在地域對應的Endpoint。以華東1(杭州)為例,Endpoint填寫為https://oss-cn-hangzhou.aliyuncs.com。*/
std::string Endpoint = "yourEndpoint";
/* yourRegion填寫Bucket所在地域對應的Region。以華東1(杭州)為例,Region填寫為cn-hangzhou。*/
std::string Region = "yourRegion";
/* 填寫源Bucket名稱,例如srcexamplebucket。*/
std::string SourceBucketName = "srcexamplebucket";
/* 填寫與源Bucket處于同一地域的目標Bucket名稱,例如destbucket。*/
std::string CopyBucketName = "destbucket";
/* 填寫源Object的完整路徑,完整路徑中不能包含Bucket名稱,例如srcdir/scrobject.txt。*/
std::string SourceObjectName = "srcdir/scrobject.txt";
/* 填寫目標Object的完整路徑,完整路徑中不能包含Bucket名稱,例如destdir/destobject.txt。*/
std::string CopyObjectName = "destdir/destobject.txt";
/* 初始化網絡等資源。*/
InitializeSdk();
ClientConfiguration conf;
conf.signatureVersion = SignatureVersionType::V4;
/* 從環境變量中獲取訪問憑證。運行本代碼示例之前,請確保已設置環境變量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。*/
auto credentialsProvider = std::make_shared<EnvironmentVariableCredentialsProvider>();
OssClient client(Endpoint, credentialsProvider, conf);
client.SetRegion(Region);
auto getObjectMetaReq = GetObjectMetaRequest(SourceBucketName, SourceObjectName);
auto getObjectMetaResult = client.GetObjectMeta(getObjectMetaReq);
if (!getObjectMetaResult.isSuccess()) {
std::cout << "GetObjectMeta fail" <<
",code:" << getObjectMetaResult.error().Code() <<
",message:" << getObjectMetaResult.error().Message() <<
",requestId:" << getObjectMetaResult.error().RequestId() << std::endl;
return -1;
}
/* 獲取源Object大小。*/
auto objectSize = getObjectMetaResult.result().ContentLength();
/* 拷貝大文件。*/
InitiateMultipartUploadRequest initUploadRequest(CopyBucketName, CopyObjectName);
/* 初始化分片拷貝事件。*/
auto uploadIdResult = client.InitiateMultipartUpload(initUploadRequest);
auto uploadId = uploadIdResult.result().UploadId();
int64_t partSize = 100 * 1024;
PartList partETagList;
int partCount = static_cast<int>(objectSize / partSize);
/* 計算分片個數。*/
if (objectSize % partSize != 0) {
partCount++;
}
/* 對每一個分片進行拷貝。*/
for (int i = 1; i <= partCount; i++) {
auto skipBytes = partSize * (i - 1);
auto size = (partSize < objectSize - skipBytes) ? partSize : (objectSize - skipBytes);
auto uploadPartCopyReq = UploadPartCopyRequest(CopyBucketName, CopyObjectName, SourceBucketName, SourceObjectName,uploadId, i);
uploadPartCopyReq.setCopySourceRange(skipBytes, skipBytes + size -1);
auto uploadPartOutcome = client.UploadPartCopy(uploadPartCopyReq);
if (uploadPartOutcome.isSuccess()) {
Part part(i, uploadPartOutcome.result().ETag());
partETagList.push_back(part);
}
else {
std::cout << "UploadPartCopy fail" <<
",code:" << uploadPartOutcome.error().Code() <<
",message:" << uploadPartOutcome.error().Message() <<
",requestId:" << uploadPartOutcome.error().RequestId() << std::endl;
}
}
/* 完成分片拷貝。*/
CompleteMultipartUploadRequest request(CopyBucketName, CopyObjectName, partETagList, uploadId);
auto outcome = client.CompleteMultipartUpload(request);
if (!outcome.isSuccess()) {
/* 異常處理。*/
std::cout << "CompleteMultipartUpload fail" <<
",code:" << outcome.error().Code() <<
",message:" << outcome.error().Message() <<
",requestId:" << outcome.error().RequestId() << std::endl;
return -1;
}
/* 釋放網絡等資源。*/
ShutdownSdk();
return 0;
}
相關文檔
關于拷貝小文件以及大文件的完整示例代碼,請參見GitHub示例。
關于拷貝小文件的API接口說明,請參見CopyObject。
關于拷貝大文件的API接口說明,請參見UploadPartCopy。