このトピックでは、バケット内または同じリージョン内のバケット間でオブジェクトをコピーする方法について説明します。
使用上の注意
このトピックでは、中国 (杭州) リージョンのパブリックエンドポイントを使用します。 OSSと同じリージョンにある他のAlibaba Cloudサービスを使用してOSSにアクセスする場合は、内部エンドポイントを使用します。 OSSでサポートされているリージョンとエンドポイントの詳細については、「リージョンとエンドポイント」をご参照ください。
このトピックでは、アクセス資格情報は環境変数から取得します。 アクセス資格情報の設定方法の詳細については、「アクセス資格情報の設定」をご参照ください。
このトピックでは、OSSエンドポイントを使用してOSSClientインスタンスを作成します。 カスタムドメイン名またはSecurity Token Service (STS) を使用してOSSClientインスタンスを作成する場合は、「OSSClientインスタンスの作成」をご参照ください。
オブジェクトをコピーするには、ソースオブジェクトに対する読み取り権限と、宛先バケットに対する読み取りおよび書き込み権限が必要です。
ソースバケットとターゲットバケットに保持ポリシーが設定されていないことを確認します。 それ以外の場合、エラーメッセージ指定したオブジェクトは不変です。 が返されます。
ソースバケットと宛先バケットは同じリージョンにある必要があります。 たとえば、中国 (杭州) リージョンにあるバケットから中国 (青島) リージョンにある別のバケットにオブジェクトをコピーすることはできません。
小さなオブジェクトをコピーする
ossClient.copyObjectメソッドを使用して、サイズが1 GB未満のオブジェクトをコピーできます。 次の表に、ossClient.copyObjectの設定方法を示します。
設定方法 | 説明 |
CopyObjectResult copyObject(String sourceBucketName, String sourceKey, String destinationBucketName, String destinationKey) | ソースバケット、ソースオブジェクト、宛先バケット、および宛先オブジェクトを指定できます。 オブジェクトがコピーされた後、宛先オブジェクトのコンテンツとメタデータは、ソースオブジェクトのコンテンツとメタデータと同じになります。 この方法は単純コピーと呼ばれます。 |
CopyObjectResult copyObject(CopyObjectRequest copyObjectRequest) | コピー先オブジェクトのメタデータとコピー条件を指定できます。 ソースオブジェクトと宛先オブジェクトのURLが同じ場合、リクエストで指定されたメタデータがソースオブジェクトのメタデータに置き換えられます。 |
次の表に、CopyObjectRequestに設定できるパラメーターを示します。
パラメーター | 説明 | メソッド |
sourceBucketName | ソースバケットの名前。 | setSourceBucketName(String sourceBucketName) |
sourceKey | ソースオブジェクトの名前。 | setSourceKey(String sourceKey) |
destinationBucketName | 宛先バケットの名前。 | setDestinationBucketName(String destinationBucketName) |
destinationKey | 宛先オブジェクトの名前。 | setDestinationKey(String destinationKey) |
newObjectMetadata | 宛先オブジェクトのメタデータ。 | setNewObjectMetadata(ObjectMetadata newObjectMetadata) |
matchingETagConstraints | コピー操作の条件。 ソースオブジェクトのETag値がリクエストで指定されたETag値と同じ場合、コピー操作が実行されます。 それ以外の場合は、エラーが返されます。 | setMatchingETagConstraints(List<String> matchingETagConstraints) |
nonmatchingEtagConstraints | コピー操作の条件。 ソースオブジェクトのETag値がリクエストで指定されたETag値と異なる場合、コピー操作が実行されます。 それ以外の場合は、エラーが返されます。 | setNonmatchingETagConstraints(List<String> nonmatchingEtagConstraints) |
unmodifiedSinceConstraint | コピー操作の条件。 リクエストで指定された時間がソースオブジェクトの実際の変更時間以降の場合、コピー操作が実行されます。 それ以外の場合は、エラーが返されます。 | setUnmodifiedSinceConstraint(Date unmodifiedSinceConstraint) |
modifiedSinceConstraint | コピー操作の条件。 要求で指定された時間の後にソースオブジェクトが変更された場合、コピー操作が実行されます。 それ以外の場合は、エラーが返されます。 | setModifiedSinceConstraint(Date modifiedSinceConstraint) |
次の表に、CopyObjectResultに設定できるパラメーターを示します。
パラメーター | 説明 | メソッド |
etag | オブジェクトの一意のタグ。 | 文字列getETag() |
lastModified | オブジェクトの最後に変更された時刻。 | 日付getLastModified() |
次のいずれかの方法を使用して、小さなオブジェクトをコピーできます。
簡易コピー
次のコードでは、単純コピーを使用して、srcexampleobject.txtという名前のオブジェクトをsrcexamplebucketからdesexamplebucketバケット内のdesexampleobject.txtという名前のオブジェクトにコピーする方法の例を示します。
com.aliyun.oss.ClientExceptionをインポートします。com.aliyun.oss.OSSをインポートします。impor t com.aliyun.oss.com mon.auth.*; com.aliyun.oss.OSSClientBuilderをインポートします。com.aliyun.oss.OSSExceptionをインポートします。com.aliyun.oss.mo delをインポートします。*; public classデモ { public static void main(String[] args) throws Exception { // この例では、中国 (杭州) リージョンのエンドポイントが使用されます。 実際のエンドポイントを指定します。 String endpoint = "https://oss-cn-hangzhou.aliyuncs.com"; // 環境変数からアクセス資格情報を取得します。 サンプルコードを実行する前に、OSS_ACCESS_KEY_IDおよびOSS_ACCESS_KEY_SECRET環境変数が設定されていることを確認してください。 EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider(); // ソースバケットの名前を指定します。 文字列sourceBucketName = "srcexamplebucket"; // ソースオブジェクトのフルパスを指定します。 バケット名をフルパスに含めないでください。 文字列sourceKey = "srcexampleobject.txt"; // 宛先バケットの名前を指定します。 宛先バケットは、ソースバケットと同じリージョンに配置する必要があります。 文字列destinationBucketName = "desexamplebucket"; // 宛先オブジェクトのフルパスを指定します。 バケット名をフルパスに含めないでください。 文字列destinationKey = "desexampleobject.txt"; // Create an OSSClient instance. OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider); try { // オブジェクトをコピーします。 CopyObjectResult result = ossClient.copyObject(sourceBucketName, sourceKey, destinationBucketName, destinationKey); System.out.println("ETag: " + result.getETag() + "LastModified: " + result.getLastModified()); } catch (Exception e) { System.out.println("Caught an OSSException, which means your request made it to OSS, " + "しかし、何らかの理由でエラー応答で拒否されました。"); System.out.println("エラーメッセージ:" + oe.getErrorMessage()); System.out.println("エラーコード:" + oe.getErrorCode()); System.out.println("リクエストID:" + oe.getRequestId()); System.out.println("ホストID:" + oe.getHostId()); } catch (ClientException e) { System.out.println("Caught an ClientException, which means the client encountered " + "a serious internal problem while trying to communicate with OSS, " + 「ネットワークにアクセスできないなど」; System.out.println("エラーメッセージ:" + ce.getMessage()); } 最後に{ if (ossClient != null) { ossClient.shutdown(); } } } }
CopyObjectRequestを使用したオブジェクトのコピー
次のコードは、CopyObjectRequestを使用して、srcexamplebucketからdesexamplebucket内のdesexampleobject.txtという名前のオブジェクトにsrcexampleobject.txtという名前のオブジェクトをコピーする方法の例を示しています。
com.aliyun.oss.ClientExceptionをインポートします。com.aliyun.oss.OSSをインポートします。impor t com.aliyun.oss.com mon.auth.*; com.aliyun.oss.OSSClientBuilderをインポートします。com.aliyun.oss.OSSExceptionをインポートします。com.aliyun.oss.mo delをインポートします。*; public classデモ { public static void main(String[] args) throws Exception { // この例では、中国 (杭州) リージョンのエンドポイントが使用されます。 実際のエンドポイントを指定します。 String endpoint = "https://oss-cn-hangzhou.aliyuncs.com"; // 環境変数からアクセス資格情報を取得します。 サンプルコードを実行する前に、OSS_ACCESS_KEY_IDおよびOSS_ACCESS_KEY_SECRET環境変数が設定されていることを確認してください。 EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider(); // ソースバケットの名前を指定します。 文字列sourceBucketName = "srcexamplebucket"; // ソースオブジェクトのフルパスを指定します。 バケット名をフルパスに含めないでください。 文字列sourceKey = "srcexampleobject.txt"; // 宛先バケットの名前を指定します。 宛先バケットは、ソースバケットと同じリージョンに配置する必要があります。 文字列destinationBucketName = "desexamplebucket"; // 宛先オブジェクトのフルパスを指定します。 バケット名をフルパスに含めないでください。 文字列destinationKey = "desexampleobject.txt"; // Create an OSSClient instance. OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider); try { // CopyObjectRequestオブジェクトを作成します。 CopyObjectRequest copyObjectRequest = new CopyObjectRequest(sourceBucketName, sourceKey, destinationBucketName, destinationKey); // オブジェクトの新しいメタデータを設定します。 ObjectMetadata meta = new ObjectMetadata(); meta.setContentType("text/plain"); // 同じ名前のオブジェクトをCopyObject操作で上書きするかどうかを指定します。 この例では、このパラメーターはtrueに設定されています。これは、同じ名前のオブジェクトを上書きしないことを指定します。 // meta.setHeader("x-oss-forbid-overwrite" 、"true"); // ソースオブジェクトのパスを指定します。 // meta.setHeader(OSSHeaders.COPY_OBJECT_SOURCE, "/examplebucket/recode-test.txt"); // ソースオブジェクトのETag値がリクエストで指定されたETag値と同じ場合、OSSはオブジェクトをコピーしてOK 200を返します。 // meta.setHeader(OSSHeaders.COPY_OBJECT_SOURCE_IF_MATCH、"5B3C1A2E053D763E1B002CC607C5 ****"); // ソースオブジェクトのETag値がリクエストで指定されたETag値と異なる場合、OSSはオブジェクトをコピーしてOK 200を返します。 // meta.setHeader(OSSHeaders.COPY_OBJECT_SOURCE_IF_NONE_MATCH、"5B3C1A2E053D763E1B002CC607C5 ****"); // リクエストで指定された時間がオブジェクトの変更時間と同じかそれ以降の場合、OSSはオブジェクトをコピーしてOK 200を返します。 // meta.setHeader(OSSHeaders.COPY_OBJECT_SOURCE_IF_UNMODIFIED_SINCE、"2021-12-09T07:01:56.000Z"); // リクエストで指定された時間後にソースオブジェクトが変更された場合、OSSはオブジェクトをコピーします。 // meta.setHeader(OSSHeaders.COPY_OBJECT_SOURCE_IF_MODIFIED_SINCE、"2021-12-09T07:01:56.000Z"); // ターゲットオブジェクトのメタデータを設定するために使用されるメソッドを指定します。 この例では、メソッドはCOPYに設定され、ソースオブジェクトのメタデータがコピー先オブジェクトにコピーされることを指定します。 // meta.setHeader(OSSHeaders.COPY_OBJECT_METADATA_DIRECTIVE、"COPY"); // オブジェクトの作成時に宛先オブジェクトの暗号化に使用されるサーバー側の暗号化アルゴリズムを指定します。 // meta.setHeader(OSSHeaders.OSS_SERVER_SIDE_ENCRYPTION, ObjectMetadata.KMS_SERVER_SIDE_ENCRYPTION); // key Management Service (KMS) によって管理されるカスタマーマスターキー (CMK) を指定します。 このパラメーターは、x-oss-server-side-encryptionをKMSに設定した場合にのみ有効になります。 // meta.setHeader(OSSHeaders.OSS_SERVER_SIDE_ENCRYPTION_KEY_ID、"9468da86-3509-4f8d-a61e-6eab1eac ****"); // 宛先オブジェクトのアクセス制御リスト (ACL) を指定します。 この例では、ACLはprivateに設定されています。これは、オブジェクトの所有者と承認されたユーザーのみがオブジェクトに対する読み取りおよび書き込み権限を持つことを指定します。 // meta.setHeader(OSSHeaders.OSS_OBJECT_ACL、CannedAccessControlList.Private); // 宛先オブジェクトのストレージクラスを指定します。 この例では、ストレージクラスはStandardに設定されています。 // meta.setHeader(OSSHeaders.OSS_STORAGE_CLASS、StorageClass.Standard); // 宛先オブジェクトのタグを指定します。 オブジェクトに対して一度に複数のタグを指定できます。 // meta.setHeader(OSSHeaders.OSS_TAGGING, "a:1"); // ターゲットオブジェクトのタグを設定するために使用されるメソッドを指定します。 この例では、メソッドはCOPYに設定され、ソースオブジェクトのタグが宛先オブジェクトにコピーされることを指定します。 // meta.setHeader(OSSHeaders.COPY_OBJECT_TAGGING_DIRECTIVE、"COPY"); copyObjectRequest.setNewObjectMetadata (メタ); // ソースオブジェクトをコピーします。 CopyObjectResult result = ossClient.copyObject(copyObjectRequest); System.out.println("ETag: " + result.getETag() + "LastModified: " + result.getLastModified()); } catch (Exception e) { System.out.println("Caught an OSSException, which means your request made it to OSS, " + "しかし、何らかの理由でエラー応答で拒否されました。"); System.out.println("エラーメッセージ:" + oe.getErrorMessage()); System.out.println("エラーコード:" + oe.getErrorCode()); System.out.println("リクエストID:" + oe.getRequestId()); System.out.println("ホストID:" + oe.getHostId()); } catch (ClientException e) { System.out.println("Caught an ClientException, which means the client encountered " + "a serious internal problem while trying to communicate with OSS, " + 「ネットワークにアクセスできないなど」; System.out.println("エラーメッセージ:" + ce.getMessage()); } 最後に{ if (ossClient != null) { ossClient.shutdown(); } } } }
大きなオブジェクトをコピーする
サイズが1 GBを超えるオブジェクトをコピーするには、オブジェクトをパーツに分割し、UploadPartCopyを使用してパーツを順番にコピーする必要があります。 マルチパートコピーを実装するには、次の手順を実行します。
ossClient.initiateMultipartUploadを使用して、マルチパートコピータスクを開始します。
ossClient.uploadPartCopyを使用して部品をコピーします。 最後の部分を除くすべての部分は100 KBより大きくなければなりません。
pleteMultipartUploadをe ossClient.comして、マルチパートコピータスクを完了します。
次のコードでは、マルチパートコピーを使用して、srcexampleobject.txtという名前のオブジェクトをsrcexamplebucketバケットからdesexampleobject.txtという名前のオブジェクトにコピーする方法の例を示します。
com.aliyun.oss.ClientExceptionをインポートします。com.aliyun.oss.OSSをインポートします。impor t com.aliyun.oss.com mon.auth.*;
com.aliyun.oss.OSSClientBuilderをインポートします。com.aliyun.oss.OSSExceptionをインポートします。com.aliyun.oss.mo delをインポートします。*;
java.util.ArrayListをインポートします。java.util.Listをインポートします。public classデモ {
public static void main(String[] args) throws Exception {
// この例では、中国 (杭州) リージョンのエンドポイントが使用されます。 実際のエンドポイントを指定します。
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// 環境変数からアクセス資格情報を取得します。 サンプルコードを実行する前に、OSS_ACCESS_KEY_IDおよびOSS_ACCESS_KEY_SECRET環境変数が設定されていることを確認してください。
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// ソースバケットの名前を指定します。
文字列sourceBucketName = "srcexamplebucket";
// ソースオブジェクトのフルパスを指定します。 バケット名をフルパスに含めないでください。
文字列sourceKey = "srcexampleobject.txt";
// 宛先バケットの名前を指定します。 宛先バケットは、ソースバケットと同じリージョンに配置する必要があります。
文字列destinationBucketName = "desexamplebucket";
// 宛先オブジェクトのフルパスを指定します。 バケット名をフルパスに含めないでください。
文字列destinationKey = "desexampleobject.txt";
// Create an OSSClient instance.
OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);
try {
ObjectMetadata objectMetadata = ossClient.getObjectMetadata(sourceBucketName, sourceKey);
// コピーするオブジェクトのサイズを照会します。
long contentLength = objectMetadata.getContentLength();
// 各パーツのサイズを10 MBに設定します。 単位:バイト
long partSize = 1024 * 1024 * 10;
// Calculate the total number of parts.
int partCount = (int) (contentLength / partSize);
if (contentLength % partSize != 0) {
partCount++;
}
System.out.println("total part count:" + partCount);
// マルチパートコピータスクを開始します。 InitiateMultipartUploadRequest操作を呼び出して、宛先オブジェクトのメタデータを指定できます。
InitiateMultipartUploadRequest initiateMultipartUploadRequest = new InitiateMultipartUploadRequest(destinationBucketName, destinationKey);
// ソースオブジェクトのContentType値とUserMetadata値をコピーします。 既定では、マルチパートコピーを使用する場合、ソースオブジェクトのContentType値とUserMetadata値はコピーされません。
ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentType(objectMetadata.getContentType());
metadata.setUserMetadata(objectMetadata.getUserMetadata());
initiateMultipartUploadRequest.setObjectMetadata(metadata);
InitiateMultipartUploadResult initiateMultipartUploadResult = ossClient.initiateMultipartUpload(initiateMultipartUploadRequest);
String uploadId = initiateMultipartUploadResult.getUploadId();
// マルチパートコピータスクを開始します。
List<PartETag> partETags = new ArrayList<PartETag>();
for (int i = 0; i <recordCount; i ++ ) {
// 各パーツのサイズを計算します。
long skipBytes = partSize * i;
long size = partSize < contentLength - skipBytes ? partSize : contentLength - skipBytes;
// UploadPartCopyRequestオブジェクトを作成します。 UploadPartCopyRequest操作を呼び出して、条件を指定できます。
UploadPartCopyRequest uploadPartCopyRequest =
新しいUploadPartCopyRequest(sourceBucketName, sourceKey, destinationBucketName, destinationKey);
uploadPartCopyRequest.setUploadId(uploadId);
uploadPartCopyRequest.setPartSize(size);
uploadPartCopyRequest.setBeginIndex(skipBytes);
uploadPartCopyRequest.setPartNumber(i + 1);
// Map headers=新しいHashMap();
// ソースオブジェクトのパスを指定します。
// headers.put(OSSHeaders.COPY_OBJECT_SOURCE, "/examplebucket/desexampleobject.txt");
// コピーするデータの範囲を指定します。 たとえば、バイト数を0 ~ 1023に設定すると、ソースオブジェクトの最初の1,024バイトがコピーされます。
// headers.put(OSSHeaders.COPY_SOURCE_RANGE、"bytes=0 ~ 1023");
// ソースオブジェクトのETag値がリクエストで指定されたETag値と同じ場合、OSSはオブジェクトをコピーしてOK 200を返します。
// headers.put(OSSHeaders.COPY_OBJECT_SOURCE_IF_MATCH、"5B3C1A2E053D763E1B002CC607C5 ****");
// ソースオブジェクトのETag値がリクエストで指定されたETag値と異なる場合、OSSはオブジェクトをコピーしてOK 200を返します。
// headers.put(OSSHeaders.COPY_OBJECT_SOURCE_IF_NONE_MATCH、"5B3C1A2E053D763E1B002CC607C5 ****");
// リクエストで指定された時間がオブジェクトの変更時間と同じかそれ以降の場合、OSSはオブジェクトをコピーしてOK 200を返します。
// headers.put(OSSHeaders.COPY_OBJECT_SOURCE_IF_UNMODIFIED_SINCE、"2021-12-09T07:01:56.000Z");
// リクエストで指定された時間後にソースオブジェクトが変更された場合、OSSはオブジェクトをコピーします。
// headers.put(OSSHeaders.COPY_OBJECT_SOURCE_IF_MODIFIED_SINCE、"2021-12-09T07:01:56.000Z");
// uploadPartCopyRequest.setHeaders(headers);
UploadPartCopyResult uploadPartCopyResult = ossClient.uploadPartCopy(uploadPartCopyRequest);
// 返されたPartETagsをpartETagsに格納します。
partETags.add(uploadPartCopyResult.getPartETag());
}
// マルチパートコピータスクを完了します。
CompleteMultipartUploadRequest completeMultipartUploadRequest = new CompleteMultipartUploadRequest(
destinationBucketName、destinationKey、uploadId、partETags);
ossClient.completeMultipartUpload(completeMultipartUploadRequest);
} catch (Exception e) {
System.out.println("Caught an OSSException, which means your request made it to OSS, "
+ "しかし、何らかの理由でエラー応答で拒否されました。");
System.out.println("エラーメッセージ:" + oe.getErrorMessage());
System.out.println("エラーコード:" + oe.getErrorCode());
System.out.println("リクエストID:" + oe.getRequestId());
System.out.println("ホストID:" + oe.getHostId());
} catch (ClientException e) {
System.out.println("Caught an ClientException, which means the client encountered "
+ "a serious internal problem while trying to communicate with OSS, "
+ 「ネットワークにアクセスできないなど」;
System.out.println("エラーメッセージ:" + ce.getMessage());
} 最後に{
if (ossClient != null) {
ossClient.shutdown();
}
}
}
}
参考資料
小さなオブジェクトをコピーする
小さなオブジェクトをコピーするために呼び出すことができるAPI操作の詳細については、「CopyObject」をご参照ください。
大きなオブジェクトをコピーする
ラージオブジェクトのコピーに使用される完全なサンプルコードの詳細については、GitHubをご覧ください。
ラージオブジェクトをコピーするために呼び出すことができるAPI操作の詳細については、「UploadPartCopy」をご参照ください。