このトピックでは、バケット内または同じリージョン内のバケット間でオブジェクトをコピーする方法について説明します。
使用上の注意
このトピックでは、中国 (杭州) リージョンのパブリックエンドポイントを使用します。 OSSと同じリージョンにある他のAlibaba CloudサービスからOSSにアクセスする場合は、内部エンドポイントを使用します。 OSSリージョンとエンドポイントの詳細については、「リージョンとエンドポイント」をご参照ください。
このトピックでは、OSSエンドポイントを使用してOSSClientインスタンスを作成します。 カスタムドメイン名またはSecurity Token Service (STS) を使用してOSSClientを作成する場合は、「OSSClientインスタンスの作成」をご参照ください。
オブジェクトをコピーするには、ソースオブジェクトに対する読み取り権限と、宛先バケットに対する読み取りおよび書き込み権限が必要です。
ソースバケットとターゲットバケットに保持ポリシーが設定されていないことを確認します。 それ以外の場合、エラーメッセージ指定したオブジェクトは不変です。 が返されます。
ソースバケットと宛先バケットは同じリージョンにある必要があります。 たとえば、中国 (杭州) リージョンにあるバケット内のオブジェクトを、中国 (青島) リージョンにある別のバケットにコピーすることはできません。
小さなオブジェクトをコピーする
client.CopyObjectを呼び出して、1 GB未満のオブジェクトをソースバケットから同じリージョン内の宛先バケットにコピーできます。 client.CopyObjectを呼び出すときにパラメーターを設定する方法を次の表に示します。
設定方法 | 説明 |
CopyObjectOutcome OssClient::CopyObject(const CopyObjectRequest &request) | コピー先オブジェクトのメタデータとコピー条件を指定できます。 ソースオブジェクトと宛先オブジェクトのURLが同じ場合、リクエストで指定されたメタデータがソースオブジェクトのメタデータに置き換えられます。 |
次のコードは、小さなオブジェクトをコピーする方法の例を示しています。
#include <alibabacloud/oss/OssClient.h>
using namespace AlibabaCloud::OSS;
int main(void)
{
/* Initialize information about the account that is used to access OSS. */
/* Specify the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com. */
std::string Endpoint = "yourEndpoint";
/* Specify the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the region to cn-hangzhou. */
std::string Region = "yourRegion";
/* Specify the name of the source bucket. Example: srcexamplebucket. */
std::string SourceBucketName = "srcexamplebucket";
/* Specify the name of the destination bucket. The destination bucket must be located in the same region as the source bucket. Example: destbucket. */
std::string CopyBucketName = "destbucket";
/* Specify the full path of the source object. Do not include the bucket name in the full path. Example: srcdir/scrobject.txt. */
std::string SourceObjectName = "srcdir/scrobject.txt";
/* Specify the full path of the destination object. Do not include the bucket name in the full path. Example: destdir/destobject.txt. */
std::string CopyObjectName = "destdir/destobject.txt";
/* Initialize resources such as network resources. */
InitializeSdk();
ClientConfiguration conf;
conf.signatureVersion = SignatureVersionType::V4;
/* Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured. */
auto credentialsProvider = std::make_shared<EnvironmentVariableCredentialsProvider>();
OssClient client(Endpoint, credentialsProvider, conf);
client.SetRegion(Region);
CopyObjectRequest request(CopyBucketName, CopyObjectName);
request.setCopySource(SourceBucketName, SourceObjectName);
/* Copy the object. */
auto outcome = client.CopyObject(request);
if (!outcome.isSuccess()) {
/* Handle exceptions. */
std::cout << "CopyObject fail" <<
",code:" << outcome.error().Code() <<
",message:" << outcome.error().Message() <<
",requestId:" << outcome.error().RequestId() << std::endl;
return -1;
}
/* Release resources such as network resources. */
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)
{
/* Initialize information about the account that is used to access OSS. */
/* Specify the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com. */
std::string Endpoint = "yourEndpoint";
/* Specify the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the region to cn-hangzhou. */
std::string Region = "yourRegion";
/* Specify the name of the source bucket. Example: srcexamplebucket. */
std::string SourceBucketName = "srcexamplebucket";
/* Specify the name of the destination bucket. The destination bucket must be located in the same region as the source bucket. Example: destbucket. */
std::string CopyBucketName = "destbucket";
/* Specify the full path of the source object. Do not include the bucket name in the full path. Example: srcdir/scrobject.txt. */
std::string SourceObjectName = "srcdir/scrobject.txt";
/* Specify the full path of the destination object. Do not include the bucket name in the full path. Example: destdir/destobject.txt. */
std::string CopyObjectName = "destdir/destobject.txt";
/* Initialize resources such as network resources. */
InitializeSdk();
ClientConfiguration conf;
conf.signatureVersion = SignatureVersionType::V4;
/* Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured. */
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;
}
/* Query the size of the source object. */
auto objectSize = getObjectMetaResult.result().ContentLength();
/* Copy the large object. */
InitiateMultipartUploadRequest initUploadRequest(CopyBucketName, CopyObjectName);
/* Initiate a multipart copy task. */
auto uploadIdResult = client.InitiateMultipartUpload(initUploadRequest);
auto uploadId = uploadIdResult.result().UploadId();
int64_t partSize = 100 * 1024;
PartList partETagList;
int partCount = static_cast<int>(objectSize / partSize);
/* Calculate the number of parts. */
if (objectSize % partSize != 0) {
partCount++;
}
/* Copy each part. */
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;
}
}
/* Complete the multipart copy task. */
CompleteMultipartUploadRequest request(CopyBucketName, CopyObjectName, partETagList, uploadId);
auto outcome = client.CompleteMultipartUpload(request);
if (!outcome.isSuccess()) {
/* Handle exceptions. */
std::cout << "CompleteMultipartUpload fail" <<
",code:" << outcome.error().Code() <<
",message:" << outcome.error().Message() <<
",requestId:" << outcome.error().RequestId() << std::endl;
return -1;
}
/* Release resources such as network resources. */
ShutdownSdk();
return 0;
}
関連ドキュメント
大きなオブジェクトと小さなオブジェクトのコピーに使用される完全なサンプルコードについては、GitHubをご覧ください。
小さなオブジェクトをコピーするために呼び出すことができるAPI操作の詳細については、「CopyObject」をご参照ください。
ラージオブジェクトをコピーするために呼び出すことができるAPI操作の詳細については、「UploadPartCopy」をご参照ください。