すべてのプロダクト
Search
ドキュメントセンター

Object Storage Service:オブジェクトのコピー

最終更新日:Oct 29, 2024

このトピックでは、バケット内または同じリージョン内のバケット間でオブジェクトをコピーする方法について説明します。

使用上の注意

  • このトピックでは、中国 (杭州) リージョンのパブリックエンドポイントを使用します。 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という名前のオブジェクトにコピーする方法の例を示します。

    import com.aliyun.oss.ClientException;
    import com.aliyun.oss.OSS;
    import com.aliyun.oss.common.auth.*;
    import com.aliyun.oss.OSSClientBuilder;
    import com.aliyun.oss.OSSException;
    import com.aliyun.oss.model.*;
    
    public class Demo {
        public static void main(String[] args) throws Exception {
            // In this example, the endpoint of the China (Hangzhou) region is used. Specify your actual endpoint. 
            String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
            // 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. 
            EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
            // Specify the name of the source bucket. 
            String sourceBucketName = "srcexamplebucket";
            // Specify the full path of the source object. Do not include the bucket name in the full path. 
            String sourceKey = "srcexampleobject.txt";
            // Specify the name of the destination bucket. The destination bucket must be located in the same region as the source bucket. 
            String destinationBucketName = "desexamplebucket";
            // Specify the full path of the destination object. Do not include the bucket name in the full path. 
            String destinationKey = "desexampleobject.txt";
            // 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.
            String region = "cn-hangzhou";
    
            // Create an OSSClient instance. 
            ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
            clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);        
            OSS ossClient = OSSClientBuilder.create()
            .endpoint(endpoint)
            .credentialsProvider(credentialsProvider)
            .clientConfiguration(clientBuilderConfiguration)
            .region(region)               
            .build();
    
            try {
                // Copy the object. 
                CopyObjectResult result = ossClient.copyObject(sourceBucketName, sourceKey, destinationBucketName, destinationKey);
                System.out.println("ETag: " + result.getETag() + " LastModified: " + result.getLastModified());
            } catch (OSSException oe) {
                System.out.println("Caught an OSSException, which means your request made it to OSS, "
                        + "but was rejected with an error response for some reason.");
                System.out.println("Error Message:" + oe.getErrorMessage());
                System.out.println("Error Code:" + oe.getErrorCode());
                System.out.println("Request ID:" + oe.getRequestId());
                System.out.println("Host ID:" + oe.getHostId());
            } catch (ClientException ce) {
                System.out.println("Caught an ClientException, which means the client encountered "
                        + "a serious internal problem while trying to communicate with OSS, "
                        + "such as not being able to access the network.");
                System.out.println("Error Message:" + ce.getMessage());
            } finally {
                if (ossClient != null) {
                    ossClient.shutdown();
                }
            }
        }
    }                   
  • CopyObjectRequestを使用したオブジェクトのコピー

    次のコードは、CopyObjectRequestを使用して、srcexamplebucketからdesexamplebucket内のdesexampleobject.txtという名前のオブジェクトにsrcexampleobject.txtという名前のオブジェクトをコピーする方法の例を示しています。

    import com.aliyun.oss.ClientException;
    import com.aliyun.oss.OSS;
    import com.aliyun.oss.common.auth.*;
    import com.aliyun.oss.OSSClientBuilder;
    import com.aliyun.oss.OSSException;
    import com.aliyun.oss.model.*;
    
    public class Demo {
        public static void main(String[] args) throws Exception {
            // In this example, the endpoint of the China (Hangzhou) region is used. Specify your actual endpoint. 
            String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
            // 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. 
            EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
            // Specify the name of the source bucket. 
            String sourceBucketName = "srcexamplebucket";
            // Specify the full path of the source object. Do not include the bucket name in the full path. 
            String sourceKey = "srcexampleobject.txt";
            // Specify the name of the destination bucket. The destination bucket must be located in the same region as the source bucket. 
            String destinationBucketName = "desexamplebucket";
            // Specify the full path of the destination object. Do not include the bucket name in the full path. 
            String destinationKey = "desexampleobject.txt";
            // 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.
            String region = "cn-hangzhou";
    
            // Create an OSSClient instance. 
            ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
            clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);        
            OSS ossClient = OSSClientBuilder.create()
            .endpoint(endpoint)
            .credentialsProvider(credentialsProvider)
            .clientConfiguration(clientBuilderConfiguration)
            .region(region)               
            .build();
    
            try {
                // Create a CopyObjectRequest object. 
                CopyObjectRequest copyObjectRequest = new CopyObjectRequest(sourceBucketName, sourceKey, destinationBucketName, destinationKey);
    
                // Configure new metadata for the object. 
                ObjectMetadata meta = new ObjectMetadata();
                meta.setContentType("text/plain");
                // Specify whether the CopyObject operation overwrites an object that has the same name. In this example, this parameter is set to true, which specifies that the operation does not overwrite an object that has the same name. 
                // meta.setHeader("x-oss-forbid-overwrite", "true");
                // Specify the path of the source object. 
                // meta.setHeader(OSSHeaders.COPY_OBJECT_SOURCE, "/examplebucket/recode-test.txt");
                // If the ETag value of the source object is the same as the ETag value specified in the request, OSS copies the object and returns 200 OK. 
                // meta.setHeader(OSSHeaders.COPY_OBJECT_SOURCE_IF_MATCH, "5B3C1A2E053D763E1B002CC607C5****");
                // If the ETag value of the source object is different from the ETag value specified in the request, OSS copies the object and returns 200 OK. 
                // meta.setHeader(OSSHeaders.COPY_OBJECT_SOURCE_IF_NONE_MATCH, "5B3C1A2E053D763E1B002CC607C5****");
                // If the time specified in the request is the same as or later than the modification time of the object, OSS copies the object and returns 200 OK. 
                // meta.setHeader(OSSHeaders.COPY_OBJECT_SOURCE_IF_UNMODIFIED_SINCE, "2021-12-09T07:01:56.000Z");
                // If the source object is modified after the time specified in the request, OSS copies the object. 
                // meta.setHeader(OSSHeaders.COPY_OBJECT_SOURCE_IF_MODIFIED_SINCE, "2021-12-09T07:01:56.000Z");
                // Specify the method that is used to configure the metadata of the destination object. In this example, the method is set to COPY, which specifies that the metadata of the source object is copied to the destination object. 
                // meta.setHeader(OSSHeaders.COPY_OBJECT_METADATA_DIRECTIVE, "COPY");
                // Specify the server-side encryption algorithm that is used to encrypt the destination object when the object is created. 
                // meta.setHeader(OSSHeaders.OSS_SERVER_SIDE_ENCRYPTION, ObjectMetadata.KMS_SERVER_SIDE_ENCRYPTION);
                // Specify the customer master key (CMK) that is managed by Key Management Service (KMS). This parameter takes effect only when you set x-oss-server-side-encryption to KMS. 
                // meta.setHeader(OSSHeaders.OSS_SERVER_SIDE_ENCRYPTION_KEY_ID, "9468da86-3509-4f8d-a61e-6eab1eac****");
                // Specify the access control list (ACL) of the destination object. In this example, the ACL is set to private, which specifies that only the object owner and authorized users have read and write permissions on the object. 
                // meta.setHeader(OSSHeaders.OSS_OBJECT_ACL, CannedAccessControlList.Private);
                // Specify the storage class of the destination object. In this example, the storage class is set to Standard. 
                // meta.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard);
                // Specify tags for the destination object. You can specify multiple tags for the object at a time. 
                // meta.setHeader(OSSHeaders.OSS_TAGGING, "a:1");
                // Specify the method that is used to configure tags for the destination object. In this example, the method is set to COPY, which specifies that the tags of the source object are copied to the destination object. 
                // meta.setHeader(OSSHeaders.COPY_OBJECT_TAGGING_DIRECTIVE, "COPY");
                copyObjectRequest.setNewObjectMetadata(meta);
    
                // Copy the source object. 
                CopyObjectResult result = ossClient.copyObject(copyObjectRequest);
                System.out.println("ETag: " + result.getETag() + " LastModified: " + result.getLastModified());
            } catch (OSSException oe) {
                System.out.println("Caught an OSSException, which means your request made it to OSS, "
                        + "but was rejected with an error response for some reason.");
                System.out.println("Error Message:" + oe.getErrorMessage());
                System.out.println("Error Code:" + oe.getErrorCode());
                System.out.println("Request ID:" + oe.getRequestId());
                System.out.println("Host ID:" + oe.getHostId());
            } catch (ClientException ce) {
                System.out.println("Caught an ClientException, which means the client encountered "
                        + "a serious internal problem while trying to communicate with OSS, "
                        + "such as not being able to access the network.");
                System.out.println("Error Message:" + ce.getMessage());
            } finally {
                if (ossClient != null) {
                    ossClient.shutdown();
                }
            }
        }
    }                 

大きなオブジェクトをコピーする

サイズが1 GBを超えるオブジェクトをコピーするには、オブジェクトをパーツに分割し、UploadPartCopyを使用してパーツを順番にコピーする必要があります。 マルチパートコピーを実装するには、次の手順を実行します。

  1. ossClient.initiateMultipartUploadを使用して、マルチパートコピータスクを開始します。

  2. ossClient.uploadPartCopyを使用して部品をコピーします。 最後の部分を除くすべての部分は100 KBより大きくなければなりません。

  3. pleteMultipartUploadをe ossClient.comして、マルチパートコピータスクを完了します。

次のコードでは、マルチパートコピーを使用して、srcexampleobject.txtという名前のオブジェクトをsrcexamplebucketバケットからdesexampleobject.txtという名前のオブジェクトにコピーする方法の例を示します。

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.*;
import java.util.ArrayList;
import java.util.List;

public class Demo {
    public static void main(String[] args) throws Exception {
        // In this example, the endpoint of the China (Hangzhou) region is used. Specify your actual endpoint. 
        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
        // 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. 
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        // Specify the name of the source bucket. 
        String sourceBucketName = "srcexamplebucket";
        // Specify the full path of the source object. Do not include the bucket name in the full path. 
        String sourceKey = "srcexampleobject.txt";
        // Specify the name of the destination bucket. The destination bucket must be located in the same region as the source bucket. 
        String destinationBucketName = "desexamplebucket";
        // Specify the full path of the destination object. Do not include the bucket name in the full path. 
        String destinationKey = "desexampleobject.txt";
        // 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.
        String region = "cn-hangzhou";

        // Create an OSSClient instance. 
        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);        
        OSS ossClient = OSSClientBuilder.create()
        .endpoint(endpoint)
        .credentialsProvider(credentialsProvider)
        .clientConfiguration(clientBuilderConfiguration)
        .region(region)               
        .build();

        try {  
            ObjectMetadata objectMetadata = ossClient.getObjectMetadata(sourceBucketName, sourceKey);
            // Query the size of the object that you want to copy. 
            long contentLength = objectMetadata.getContentLength();

            // Set the size of each part to 10 MB. Unit: bytes. 
            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);

            // Initiate a multipart copy task. You can call the InitiateMultipartUploadRequest operation to specify the metadata of the destination object. 
            InitiateMultipartUploadRequest initiateMultipartUploadRequest = new InitiateMultipartUploadRequest(destinationBucketName, destinationKey);
            // Copy the ContentType and UserMetadata values of the source object. By default, the ContentType and UserMetadata values of the source object are not copied when you use multipart copy. 
            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setContentType(objectMetadata.getContentType());
            metadata.setUserMetadata(objectMetadata.getUserMetadata());
            initiateMultipartUploadRequest.setObjectMetadata(metadata);
            InitiateMultipartUploadResult initiateMultipartUploadResult = ossClient.initiateMultipartUpload(initiateMultipartUploadRequest);
            String uploadId = initiateMultipartUploadResult.getUploadId();

            // Start the multipart copy task. 
            List<PartETag> partETags = new ArrayList<PartETag>();
            for (int i = 0; i < partCount; i++) {
                // Calculate the size of each part. 
                long skipBytes = partSize * i;
                long size = partSize < contentLength - skipBytes ? partSize : contentLength - skipBytes;

                // Create an UploadPartCopyRequest object. You can call the UploadPartCopyRequest operation to specify conditions. 
                UploadPartCopyRequest uploadPartCopyRequest =
                        new UploadPartCopyRequest(sourceBucketName, sourceKey, destinationBucketName, destinationKey);
                uploadPartCopyRequest.setUploadId(uploadId);
                uploadPartCopyRequest.setPartSize(size);
                uploadPartCopyRequest.setBeginIndex(skipBytes);
                uploadPartCopyRequest.setPartNumber(i + 1);
                //Map headers = new HashMap();
                // Specify the path of the source object. 
                // headers.put(OSSHeaders.COPY_OBJECT_SOURCE, "/examplebucket/desexampleobject.txt");
                // Specify the range of data that you want to copy. For example, if you set bytes to 0~1023, the first 1,024 bytes of the source object are copied. 
                // headers.put(OSSHeaders.COPY_SOURCE_RANGE, "bytes=0~1023");
                // If the ETag value of the source object is the same as the ETag value specified in the request, OSS copies the object and returns 200 OK. 
                // headers.put(OSSHeaders.COPY_OBJECT_SOURCE_IF_MATCH, "5B3C1A2E053D763E1B002CC607C5****");
                // If the ETag value of the source object is different from the ETag value specified in the request, OSS copies the object and returns 200 OK. 
                // headers.put(OSSHeaders.COPY_OBJECT_SOURCE_IF_NONE_MATCH, "5B3C1A2E053D763E1B002CC607C5****");
                // If the time specified in the request is the same as or later than the modification time of the object, OSS copies the object and returns 200 OK. 
                // headers.put(OSSHeaders.COPY_OBJECT_SOURCE_IF_UNMODIFIED_SINCE, "2021-12-09T07:01:56.000Z");
                // If the source object is modified after the time that is specified in the request, OSS copies the object. 
                // headers.put(OSSHeaders.COPY_OBJECT_SOURCE_IF_MODIFIED_SINCE, "2021-12-09T07:01:56.000Z");
                // uploadPartCopyRequest.setHeaders(headers);
                UploadPartCopyResult uploadPartCopyResult = ossClient.uploadPartCopy(uploadPartCopyRequest);

                // Store the returned PartETags in partETags. 
                partETags.add(uploadPartCopyResult.getPartETag());
            }

            // Complete the multipart copy task. 
            CompleteMultipartUploadRequest completeMultipartUploadRequest = new CompleteMultipartUploadRequest(
                    destinationBucketName, destinationKey, uploadId, partETags);
            ossClient.completeMultipartUpload(completeMultipartUploadRequest);
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }
}

関連ドキュメント

  • 小さなオブジェクトをコピーする

    小さなオブジェクトをコピーするために呼び出すことができるAPI操作の詳細については、「CopyObject」をご参照ください。

  • 大きなオブジェクトをコピーする

    • ラージオブジェクトのコピーに使用される完全なサンプルコードの詳細については、GitHubをご覧ください。

    • ラージオブジェクトをコピーするために呼び出すことができるAPI操作の詳細については、「UploadPartCopy」をご参照ください。