このトピックでは、Object Storage Service (OSS) のバージョン管理が有効になっているバケット内のオブジェクトをコピーする方法について説明します。CopyObject を呼び出して最大 1 GB のオブジェクトをコピーし、UploadPartCopy を呼び出して 1 GB を超えるオブジェクトをコピーできます。
使用上の注意
このトピックでは、中国 (杭州) リージョンのパブリックエンドポイントを使用しています。OSS と同じリージョン内の他の Alibaba Cloud サービスから OSS にアクセスする場合は、内部エンドポイントを使用します。OSS のリージョンとエンドポイントの詳細については、「リージョンとエンドポイント」をご参照ください。
このトピックでは、OSS エンドポイントを使用して OSSClient インスタンスを作成します。カスタムドメイン名または Security Token Service (STS) を使用して OSSClient インスタンスを作成する場合は、「初期化」をご参照ください。
オブジェクトをコピーするには、
oss:GetObject
およびoss:PutObject
権限が必要です。詳細については、「RAM ユーザーへのカスタムポリシーのアタッチ」をご参照ください。
小さなオブジェクトのコピー
CopyObject を呼び出して、同じリージョン内のソースバケットからデスティネーションバケットに最大 1 GB のオブジェクトをコピーできます。
デフォルトでは、x-oss-copy-source ヘッダーは、コピーするオブジェクトの現在のバージョンを指定します。オブジェクトの現在のバージョンが削除マーカーの場合、OSS は HTTP 404 ステータスコードを返します。HTTP ステータスコードは、オブジェクトが存在しないことを示します。指定したオブジェクトバージョンをコピーするために、versionId を x-oss-copy-source リクエストヘッダーに追加できます。削除マーカーはコピーできません。
オブジェクトの以前のバージョンを同じバケットにコピーできます。コピーされた以前のバージョンは、オブジェクトの現在のバージョンになります。このようにして、オブジェクトの以前のバージョンが復元されます。
デスティネーションバケットでバージョン管理が有効になっている場合、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 操作は、指定されたオブジェクトの現在のバージョンからデータをコピーすることによってパーツをアップロードします。オブジェクトの指定されたバージョンをコピーするために、バージョン ID を x-oss-copy-source ヘッダーに追加できます。例: x-oss-copy-source: /SourceBucketName/SourceObjectName?versionId=CAEQMxiBgICAof2D0BYiIDJhMGE3N2M1YTI1NDQzOGY5NTkyNTI3MGYyMzJm****。
SourceObjectName パラメータの値は URL エンコードする必要があります。コピーされたオブジェクトのバージョン ID は、レスポンスの x-oss-copy-source-version-id ヘッダーの値として返されます。
リクエストでバージョン ID が指定されておらず、ソースオブジェクトの現在のバージョンが削除マーカーの場合、OSS は 404 Not Found を返します。リクエストでバージョン ID が指定されており、ソースオブジェクトの指定されたバージョンが削除マーカーの場合、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」をご参照ください。