このトピックでは、Object Storage Service (OSS) のバージョン管理が有効なバケットでオブジェクトをコピーする方法について説明します。サイズが 1 GB 以下のオブジェクトをコピーするには CopyObject を呼び出し、サイズが 1 GB を超えるオブジェクトをコピーするには UploadPartCopy を呼び出します。
注意事項
このトピックでは、中国 (杭州) リージョンのパブリックエンドポイントを使用します。OSS と同じリージョンにある他の Alibaba Cloud サービスから OSS にアクセスする場合は、内部エンドポイントを使用してください。OSS のリージョンとエンドポイントの詳細については、「リージョンとエンドポイント」をご参照ください。
このトピックでは、OSS エンドポイントを使用して OSSClient インスタンスを作成します。カスタムドメイン名または Security Token Service (STS) を使用して OSSClient インスタンスを作成する場合は、「初期化 (C# SDK V1)」をご参照ください。
オブジェクトをコピーするには、
oss:GetObjectおよびoss:PutObject権限が必要です。詳細については、「RAM ユーザーへのカスタムポリシーのアタッチ」をご参照ください。
小規模オブジェクトのコピー
1 GB 未満のファイルの場合は、CopyObject メソッドを使用して、同じリージョン内のソースバケットから宛先バケットにファイルをコピーします。
デフォルトでは、x-oss-copy-source ヘッダーはコピーするオブジェクトの現在のバージョンを指定します。オブジェクトの現在のバージョンが削除マーカーの場合、OSS は HTTP 404 ステータスコードを返します。この HTTP ステータスコードは、オブジェクトが存在しないことを示します。x-oss-copy-source リクエストヘッダーに versionId を追加して、指定したオブジェクトバージョンをコピーできます。削除マーカーはコピーできません。
オブジェクトの以前のバージョンを同じバケットにコピーできます。コピーされた以前のバージョンは、オブジェクトの現在のバージョンになります。これにより、オブジェクトの以前のバージョンが復元されます。
宛先バケットでバージョン管理が有効になっている場合、OSS は宛先オブジェクトの一意のバージョン ID を生成します。バージョン ID は、レスポンスの x-oss-version-id ヘッダーの値として返されます。宛先バケットでバージョン管理が無効または一時停止されている場合、OSS は ID が null のバージョンを宛先オブジェクトに生成し、ID が null の元のバージョンを上書きします。
バージョン管理が有効または一時停止されている宛先バケットに、追加可能オブジェクトをコピーすることはできません。
次のコードは、小規模オブジェクトをコピーする方法を示しています。
using Aliyun.OSS;
using Aliyun.OSS.Common;
// バケットが配置されているリージョンのエンドポイントを指定します。たとえば、バケットが中国 (杭州) リージョンにある場合、エンドポイントを https://oss-cn-hangzhou.aliyuncs.com に設定します。
var endpoint = "yourEndpoint";
// 環境変数からアクセス認証情報を取得します。サンプルコードを実行する前に、OSS_ACCESS_KEY_ID および OSS_ACCESS_KEY_SECRET 環境変数が設定されていることを確認してください。
var accessKeyId = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_ID");
var accessKeySecret = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_SECRET");
// ソースバケットの名前を指定します。
var sourceBucket = "yourSourceBucketName";
// ソースオブジェクトの完全なパスを指定します。バケット名は完全なパスに含めないでください。
var sourceObject = "yourSourceObjectName";
// 宛先バケットの名前を指定します。宛先バケットはソースバケットと同じリージョンにある必要があります。
var targetBucket = "yourDestBucketName";
// 宛先オブジェクトの完全なパスを指定します。バケット名は完全なパスに含めないでください。
var targetObject = "yourDestObjectName";
// ソースオブジェクトのバージョン ID を指定します。
var versionid = "yourArchiveObjectVersionid";
// バケットが配置されているリージョンを指定します。たとえば、バケットが中国 (杭州) リージョンにある場合、リージョンを cn-hangzhou に設定します。
const string region = "cn-hangzhou";
// ClientConfiguration インスタンスを作成し、要件に基づいてデフォルトのパラメーターを変更します。
var conf = new ClientConfiguration();
// 署名アルゴリズム V4 を使用します。
conf.SignatureVersion = SignatureVersion.V4;
// OSSClient インスタンスを作成します。
var client = new OssClient(endpoint, accessKeyId, accessKeySecret, conf);
client.SetRegion(region);
try
{
var metadata = new ObjectMetadata();
metadata.AddHeader("mk1", "mv1");
metadata.AddHeader("mk2", "mv2");
var req = new CopyObjectRequest(sourceBucket, sourceObject, targetBucket, targetObject)
{
// NewObjectMetadata の値が null の場合、COPY モードが使用され、ソースオブジェクトのメタデータが宛先オブジェクトにコピーされます。NewObjectMetadata の値が null でない場合、REPLACE モードが使用され、ソースオブジェクトのメタデータが宛先オブジェクトのメタデータを上書きします。
NewObjectMetadata = metadata,
// オブジェクトのバージョン ID を指定します。
SourceVersionId = versionid
};
// オブジェクトをコピーします。
var result = client.CopyObject(req);
Console.WriteLine("Copy object succeeded, vesionid:{0}", result.VersionId);
}
catch (OssException ex)
{
Console.WriteLine("Failed with error code: {0}; Error info: {1}. \nRequestID: {2} \tHostID: {3}",
ex.ErrorCode, ex.Message, ex.RequestId, ex.HostId);
}
catch (Exception ex)
{
Console.WriteLine("Failed with error info: {0}", ex.Message);
}大規模オブジェクトのコピー
1 GB を超えるファイルの場合は、マルチパートコピー (UploadPartCopy) メソッドを使用します。
デフォルトでは、UploadPartCopy 操作は、既存のオブジェクトの現在のバージョンからパートをコピーします。オブジェクトの特定のバージョンからパートをコピーするには、`x-oss-copy-source` リクエストヘッダーに versionId サブリソースを追加します。例:`x-oss-copy-source: /SourceBucketName/SourceObjectName?versionId=CAEQMxiBgICAof2D0BYiIDJhMGE3N2M1YTI1NDQzOGY5NTkyNTI3MGYyMzJm****`。
`SourceObjectName` は URL エンコードする必要があります。レスポンスは、`x-oss-copy-source-version-id` でソースオブジェクトのバージョン ID を返します。
versionId を指定せず、ソースオブジェクトの現在のバージョンが削除マーカーである場合、OSS は 404 Not Found を返します。削除マーカーの versionId を指定した場合、OSS は 400 Bad Request を返します。
次のコードは、マルチパートコピーを実行する方法を示しています。
using System;
using System.Collections.Generic;
using Aliyun.OSS;
using Aliyun.OSS.Common;
namespace Samples
{
public class Program
{
public static void Main(string[] args)
{
// バケットが配置されているリージョンのエンドポイントを指定します。たとえば、バケットが中国 (杭州) リージョンにある場合、エンドポイントを https://oss-cn-hangzhou.aliyuncs.com に設定します。
var endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// 環境変数からアクセス認証情報を取得します。サンプルコードを実行する前に、OSS_ACCESS_KEY_ID および OSS_ACCESS_KEY_SECRET 環境変数が設定されていることを確認してください。
var accessKeyId = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_ID");
var accessKeySecret = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_SECRET");
// ソースバケットの名前を指定します。
var sourceBucket = "yourSourceBucketName";
// ソースオブジェクトの完全なパスを指定します。バケット名は完全なパスに含めないでください。
var sourceObject = "yourSourceObjectName";
// 宛先バケットの名前を指定します。宛先バケットはソースバケットと同じリージョンにある必要があります。
var targetBucket = "yourDestBucketName";
// 宛先オブジェクトの完全なパスを指定します。バケット名は完全なパスに含めないでください。
var targetObject = "yourDestObjectName";
// ソースオブジェクトのバージョン ID を指定します。
var sourceObjectVersionid = "yourSourceObjectVersionid";
var partSize = 50 * 1024 * 1024;
// OSSClient インスタンスを作成します。
var client = new OssClient(endpoint, accessKeyId, accessKeySecret);
try
{
// マルチパートコピータスクを開始します。InitiateMultipartUploadRequest 操作を呼び出して、宛先オブジェクトのメタデータを指定できます。
var initRequest = new InitiateMultipartUploadRequest(targetBucket, targetObject);
var result = client.InitiateMultipartUpload(initRequest);
// アップロード ID を表示します。
var uploadId = result.UploadId;
Console.WriteLine("Init multipart upload succeeded, Upload Id: {0}", result.UploadId);
// パートの総数を計算します。
var request = new GetObjectMetadataRequest(sourceBucket, sourceObject)
{
// オブジェクトのバージョン ID を指定します。
VersionId = sourceObjectVersionid
};
var metadata = client.GetObjectMetadata(request);
var fileSize = metadata.ContentLength;
var partCount = (int)fileSize / partSize;
if (fileSize % partSize != 0)
{
partCount++;
}
// マルチパートコピータスクを開始します。
var partETags = new List<PartETag>();
for (var i = 0; i < partCount; i++)
{
var skipBytes = (long)partSize * i;
var size = (partSize < fileSize - skipBytes) ? partSize : (fileSize - skipBytes);
// UploadPartCopyRequest リクエストを作成します。UploadPartCopyRequest 操作を呼び出して条件を指定できます。
var uploadPartCopyRequest = new UploadPartCopyRequest(targetBucket, targetObject, sourceBucket, sourceObject, uploadId)
{
PartSize = size,
PartNumber = i + 1,
// BeginIndex を使用して、パートをアップロードする開始位置を見つけます。
BeginIndex = skipBytes,
// オブジェクトのバージョン ID を指定します。
VersionId = sourceObjectVersionid
};
// uploadPartCopy 操作を呼び出して各パートをコピーします。
var uploadPartCopyResult = client.UploadPartCopy(uploadPartCopyRequest);
Console.WriteLine("UploadPartCopy : {0}", i);
partETags.Add(uploadPartCopyResult.PartETag);
}
// マルチパートコピータスクを完了します。
var completeMultipartUploadRequest =
new CompleteMultipartUploadRequest(targetBucket, targetObject, uploadId);
// partETags は partETag のリストです。OSS は partETags を受信した後、各パートを検証します。すべてのパートが検証された後、OSS はこれらのパートを完全なオブジェクトに結合します。
foreach (var partETag in partETags)
{
completeMultipartUploadRequest.PartETags.Add(partETag);
}
var completeMultipartUploadResult = client.CompleteMultipartUpload(completeMultipartUploadRequest);
Console.WriteLine("CompleteMultipartUpload succeeded, vesionid:{0}", completeMultipartUploadResult.VersionId);
}
catch (OssException ex)
{
Console.WriteLine("Failed with error code: {0}; Error info: {1}. \nRequestID: {2} \tHostID: {3}",
ex.ErrorCode, ex.Message, ex.RequestId, ex.HostId);
}
catch (Exception ex)
{
Console.WriteLine("Failed with error info: {0}", ex.Message);
}
}
}
}関連ドキュメント
小規模オブジェクトをコピーするために呼び出すことができる API 操作の詳細については、「CopyObject」をご参照ください。
大規模オブジェクトをコピーするために呼び出すことができる API 操作の詳細については、「UploadPartCopy」をご参照ください。