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

Object Storage Service:Copy objects

最終更新日:Mar 21, 2026

オブジェクトのコンテンツを変更せずに、同じリージョン内のソースバケットから送信先バケットへオブジェクトをコピーします。

CopyObject 操作を使用すると、次のことができます。

  • 同じリージョン内の別のバケットにオブジェクトをバックアップします。

  • ダウンロードと再アップロードなしで、バケット間でオブジェクトを移行します。

  • 同じキーにコピーすることで、オブジェクトのストレージクラス、アクセス制御リスト (ACL)、メタデータ、またはタグを変更します。

前提条件

オブジェクトをコピーする前に、以下を確認してください。

  • ソースオブジェクトに対する読み取り権限

  • 送信先バケットに対する読み書き権限

いずれかの権限が不足している場合、コピー操作は失敗します。

制限事項

  • クロスリージョンコピーはサポートされていません。たとえば、中国 (杭州) と中国 (上海) の間でオブジェクトをコピーすることはできません。

  • 1 GB を超えるオブジェクトは、マルチパートコピー方式 (UploadPartCopy) を使用する必要があります。ossbrowser は 5 GB までのオブジェクトをサポートします。

  • ソースバケットまたは送信先バケットに保持ポリシーが設定されている場合、コピー操作はエラー「指定されたオブジェクトは変更できません」を返します。

コピー方法の選択

メソッドオブジェクトサイズ備考
ossbrowser5 GB までGUI ツール。コード不要
OSS SDK (CopyObject)1 GB までプログラムによるアクセスに推奨
OSS SDK (UploadPartCopy)1 GB を超えるマルチパートコピー。「概要
ossutil任意のサイズCLI ツール
CopyObject API1 回の呼び出しにつき 1 GB まで直接 API 呼び出し。署名計算が必要

上書き動作

デフォルトでは、送信先バケット内の既存のオブジェクトと同じキーを持つオブジェクトをコピーすると、そのオブジェクトは上書きされます。意図しない上書きを防ぐには、次のいずれかの方法を使用します。

  • 送信先バケットでバージョン管理を有効にします。 上書きされたオブジェクトは以前のバージョンとして保存され、いつでも回復できます。詳細については、「バージョン管理」をご参照ください。

  • `x-oss-forbid-overwrite` ヘッダーを `true` に設定します。 送信先キーが既に存在する場合、コピーは失敗し、OSS は FileAlreadyExists エラーコードを返します。

コストに関する考慮事項

多数のオブジェクトをコピーし、すぐにストレージクラスをディープコールドアーカイブストレージに設定すると、高額な PUT リクエスト料金が発生する可能性があります。コストを削減するには、コピー後にオブジェクトをディープコールドアーカイブストレージにトランジションするようにライフサイクルルールを設定します。

オブジェクトのコピー

OSS SDK の使用

次の例では、CopyObject 操作を使用して 1 GB 未満のオブジェクトをコピーします。1 GB を超えるオブジェクトの場合は、UploadPartCopy を使用します。「概要」をご参照ください。

すべての例は、環境変数 (OSS_ACCESS_KEY_ID および OSS_ACCESS_KEY_SECRET) から認証情報を読み取ります。コードを実行する前に、これらの変数を設定してください。

コピー時のメタデータ動作

デフォルトでは、OSS はソースオブジェクトのメタデータを送信先オブジェクトにコピーします (COPY モード)。メタデータを置き換えるには、x-oss-metadata-directiveREPLACE に設定し、リクエストで新しいメタデータ値を指定します。メタデータを置き換える場合、すべてのメタデータフィールドを明示的に宣言する必要があります。フィールドを省略すると、送信先オブジェクトから削除されます。

<details> <summary>Python</summary>

import argparse
import alibabacloud_oss_v2 as oss

parser = argparse.ArgumentParser(description="copy object sample")
parser.add_argument('--region', required=True, help='The region in which the bucket is located.')
parser.add_argument('--bucket', required=True, help='The name of the destination bucket.')
parser.add_argument('--endpoint', help='The endpoint of the region.')
parser.add_argument('--key', required=True, help='The key of the destination object.')
parser.add_argument('--source_key', required=True, help='The key of the source object.')
parser.add_argument('--source_bucket', required=True, help='The name of the source bucket.')

def main():
    args = parser.parse_args()

    credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()
    cfg = oss.config.load_default()
    cfg.credentials_provider = credentials_provider
    cfg.region = args.region

    if args.endpoint is not None:
        cfg.endpoint = args.endpoint

    client = oss.Client(cfg)

    result = client.copy_object(oss.CopyObjectRequest(
        bucket=args.bucket,
        key=args.key,
        source_key=args.source_key,
        source_bucket=args.source_bucket,
    ))

    print(f'status code: {result.status_code},'
          f' request id: {result.request_id},'
          f' version id: {result.version_id},'
          f' hash crc64: {result.hash_crc64},'
          f' source version id: {result.source_version_id},'
          f' server side encryption: {result.server_side_encryption},'
          f' server side data encryption: {result.server_side_data_encryption},'
          f' last modified: {result.last_modified},'
          f' etag: {result.etag}')

if __name__ == "__main__":
    main()

</details>

<details> <summary>Java</summary>

import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.model.*;

public class Demo {
    public static void main(String[] args) throws Exception {
        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com"; // ご利用のエンドポイントに置き換えてください
        String region = "cn-hangzhou";                            // ご利用のリージョンに置き換えてください
        String sourceBucketName = "srcexamplebucket";
        String sourceKey = "srcexampleobject.txt";
        String destinationBucketName = "desexamplebucket";        // 同じリージョンである必要があります
        String destinationKey = "desexampleobject.txt";

        EnvironmentVariableCredentialsProvider credentialsProvider =
            CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();

        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);

        OSS ossClient = OSSClientBuilder.create()
            .endpoint(endpoint)
            .credentialsProvider(credentialsProvider)
            .clientConfiguration(clientBuilderConfiguration)
            .region(region)
            .build();

        try {
            CopyObjectRequest copyObjectRequest = new CopyObjectRequest(
                sourceBucketName, sourceKey,
                destinationBucketName, destinationKey
            );

            CopyObjectResult result = ossClient.copyObject(copyObjectRequest);
            System.out.println("ETag: " + result.getETag() + " LastModified: " + result.getLastModified());
        } catch (OSSException oe) {
            System.out.println("Error Code: " + oe.getErrorCode());
            System.out.println("Request ID: " + oe.getRequestId());
        } catch (ClientException ce) {
            System.out.println("Client Error: " + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }
}

</details>

<details> <summary>Go</summary>

package main

import (
    "context"
    "flag"
    "log"

    "github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss"
    "github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials"
)

var (
    region         string
    srcBucketName  string
    srcObjectName  string
    destBucketName string
    destObjectName string
)

func init() {
    flag.StringVar(&region, "region", "", "The region in which the bucket is located.")
    flag.StringVar(&srcBucketName, "src-bucket", "", "The name of the source bucket.")
    flag.StringVar(&srcObjectName, "src-object", "", "The name of the source object.")
    flag.StringVar(&destBucketName, "dest-bucket", "", "The name of the destination bucket.")
    flag.StringVar(&destObjectName, "dest-object", "", "The name of the destination object.")
}

func main() {
    flag.Parse()

    if len(srcBucketName) == 0 {
        log.Fatalf("invalid parameters, source bucket name required")
    }
    if len(region) == 0 {
        log.Fatalf("invalid parameters, region required")
    }
    if len(destBucketName) == 0 {
        destBucketName = srcBucketName // Default to source bucket for same-bucket copy
    }
    if len(srcObjectName) == 0 {
        log.Fatalf("invalid parameters, source object name required")
    }
    if len(destObjectName) == 0 {
        log.Fatalf("invalid parameters, destination object name required")
    }

    cfg := oss.LoadDefaultConfig().
        WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
        WithRegion(region)

    client := oss.NewClient(cfg)

    request := &oss.CopyObjectRequest{
        Bucket:       oss.Ptr(destBucketName),
        Key:          oss.Ptr(destObjectName),
        SourceKey:    oss.Ptr(srcObjectName),
        SourceBucket: oss.Ptr(srcBucketName),
    }

    result, err := client.CopyObject(context.TODO(), request)
    if err != nil {
        log.Fatalf("failed to copy object %v", err)
    }
    log.Printf("copy object result: %#v\n", result)
}

</details>

<details> <summary>PHP</summary>

<?php

require_once __DIR__ . '/../vendor/autoload.php';

use AlibabaCloud\Oss\V2 as Oss;

$optsdesc = [
    "region"     => ['help' => 'The region in which the bucket is located.', 'required' => true],
    "endpoint"   => ['help' => 'The endpoint of the region.', 'required' => false],
    "bucket"     => ['help' => 'The name of the destination bucket.', 'required' => true],
    "key"        => ['help' => 'The key of the destination object.', 'required' => true],
    "src-bucket" => ['help' => 'The name of the source bucket.', 'required' => false],
    "src-key"    => ['help' => 'The key of the source object.', 'required' => true],
];

$longopts = array_map(fn($key) => "$key:", array_keys($optsdesc));
$options = getopt("", $longopts);

foreach ($optsdesc as $key => $value) {
    if ($value['required'] === true && empty($options[$key])) {
        echo "Error: --$key is required. " . $value['help'] . PHP_EOL;
        exit(1);
    }
}

$credentialsProvider = new Oss\Credentials\EnvironmentVariableCredentialsProvider();
$cfg = Oss\Config::loadDefault();
$cfg->setCredentialsProvider($credentialsProvider);
$cfg->setRegion($options["region"]);

if (isset($options["endpoint"])) {
    $cfg->setEndpoint($options["endpoint"]);
}

$client = new Oss\Client($cfg);

$request = new Oss\Models\CopyObjectRequest(
    bucket: $options["bucket"],
    key: $options["key"]
);

if (!empty($options["src-bucket"])) {
    $request->sourceBucket = $options["src-bucket"];
}
$request->sourceKey = $options["src-key"];

$result = $client->copyObject($request);

printf(
    'status code: %s' . PHP_EOL .
    'request id: %s' . PHP_EOL,
    $result->statusCode,
    $result->requestId
);

</details>

<details> <summary>Node.js</summary>

const OSS = require('ali-oss');

const client = new OSS({
  region: 'yourRegion',                                    // ご利用のリージョンに置き換えてください
  accessKeyId: process.env.OSS_ACCESS_KEY_ID,
  accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
  authorizationV4: true,
  bucket: 'examplebucket',
});

async function copyObject() {
  try {
    const result = await client.copy('destexampleobject.txt', 'srcexampleobject.txt');
    console.log(result);
  } catch (e) {
    console.log(e);
  }
}

copyObject();

</details>

<details> <summary>C#</summary>

using Aliyun.OSS;
using Aliyun.OSS.Common;

var endpoint = "https://oss-cn-hangzhou.aliyuncs.com"; // ご利用のエンドポイントに置き換えてください
var region = "cn-hangzhou";                            // ご利用のリージョンに置き換えてください
var accessKeyId = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_ID");
var accessKeySecret = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_SECRET");

var sourceBucket = "srcexamplebucket";
var sourceObject = "srcdir/srcobject.txt";
var targetBucket = "destbucket";             // 同じリージョンである必要があります
var targetObject = "destdir/destobject.txt";

var conf = new ClientConfiguration();
conf.SignatureVersion = SignatureVersion.V4;

var client = new OssClient(endpoint, accessKeyId, accessKeySecret, conf);
client.SetRegion(region);

try
{
    var req = new CopyObjectRequest(sourceBucket, sourceObject, targetBucket, targetObject);
    client.CopyObject(req);
    Console.WriteLine("Copy object succeeded");
}
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);
}

</details>

<details> <summary>Ruby</summary>

require 'aliyun/oss'

client = Aliyun::OSS::Client.new(
  endpoint: 'https://oss-cn-hangzhou.aliyuncs.com', # ご利用のエンドポイントに置き換えてください
  access_key_id: ENV['OSS_ACCESS_KEY_ID'],
  access_key_secret: ENV['OSS_ACCESS_KEY_SECRET']
)

bucket = client.get_bucket('examplebucket')

# オブジェクトとそのメタデータをコピーします
bucket.copy_object('destobject.txt', 'srcobject.txt',
  :meta_directive => Aliyun::OSS::MetaDirective::COPY)

# オブジェクトをコピーし、そのメタデータを置き換えます
bucket.copy_object('destobject.txt', 'srcobject.txt',
  :metas => {'year' => '2017'},
  :meta_directive => Aliyun::OSS::MetaDirective::REPLACE)

</details>

<details> <summary>Android (Java)</summary>

String srcBucketName = "srcbucket";
String srcObjectKey = "dir1/srcobject.txt";
String destBucketName = "destbucket"; // 同じリージョンである必要があります
String destObjectKey = "dir2/destobject.txt";

CopyObjectRequest copyObjectRequest = new CopyObjectRequest(
    srcBucketName, srcObjectKey,
    destBucketName, destObjectKey
);

OSSAsyncTask copyTask = oss.asyncCopyObject(copyObjectRequest,
    new OSSCompletedCallback<CopyObjectRequest, CopyObjectResult>() {
        @Override
        public void onSuccess(CopyObjectRequest request, CopyObjectResult result) {
            Log.d("copyObject", "copy success!");
        }

        @Override
        public void onFailure(CopyObjectRequest request,
                              ClientException clientException,
                              ServiceException serviceException) {
            if (clientException != null) {
                clientException.printStackTrace();
            }
            if (serviceException != null) {
                Log.e("ErrorCode", serviceException.getErrorCode());
                Log.e("RequestId", serviceException.getRequestId());
                Log.e("HostId", serviceException.getHostId());
                Log.e("RawMessage", serviceException.getRawMessage());
            }
        }
    });

</details>

<details> <summary>iOS (Objective-C)</summary>

OSSCopyObjectRequest *copy = [OSSCopyObjectRequest new];
copy.sourceBucketName = @"sourcebucket";
copy.sourceObjectKey = @"dir1/srcobject.txt";
copy.bucketName = @"destbucket";
copy.objectKey = @"dir2/destobject.txt";

OSSTask *task = [client copyObject:copy];
[task continueWithBlock:^id(OSSTask *task) {
    if (!task.error) {
        NSLog(@"copy object success!");
    } else {
        NSLog(@"copy object failed, error: %@", task.error);
    }
    return nil;
}];

</details>

<details> <summary>C++</summary>

#include <alibabacloud/oss/OssClient.h>
using namespace AlibabaCloud::OSS;

int main(void)
{
    std::string Endpoint = "yourEndpoint"; // ご利用のエンドポイントに置き換えてください
    std::string Region = "yourRegion";     // ご利用のリージョンに置き換えてください
    std::string SourceBucketName = "srcexamplebucket";
    std::string CopyBucketName = "destbucket"; // 同じリージョンである必要があります
    std::string SourceObjectName = "srcdir/srcobject.txt";
    std::string CopyObjectName = "destdir/destobject.txt";

    InitializeSdk();

    ClientConfiguration conf;
    conf.signatureVersion = SignatureVersionType::V4;

    auto credentialsProvider = std::make_shared<EnvironmentVariableCredentialsProvider>();
    OssClient client(Endpoint, credentialsProvider, conf);
    client.SetRegion(Region);

    CopyObjectRequest request(CopyBucketName, CopyObjectName);
    request.setCopySource(SourceBucketName, SourceObjectName);

    auto outcome = client.CopyObject(request);

    if (!outcome.isSuccess()) {
        std::cout << "CopyObject failed"
                  << ", code: " << outcome.error().Code()
                  << ", message: " << outcome.error().Message()
                  << ", requestId: " << outcome.error().RequestId() << std::endl;
        ShutdownSdk();
        return -1;
    }

    ShutdownSdk();
    return 0;
}

</details>

<details> <summary>C</summary>

#include "oss_api.h"
#include "aos_http_io.h"

const char *endpoint = "yourEndpoint";          // ご利用のエンドポイントに置き換えてください
const char *region = "yourRegion";              // ご利用のリージョンに置き換えてください
const char *source_bucket_name = "yourSourceBucketName";
const char *source_object_name = "yourSourceObjectName";
const char *dest_bucket_name = "yourDestBucketName";  // 同じリージョンである必要があります
const char *dest_object_name = "yourDestObjectName";

void init_options(oss_request_options_t *options)
{
    options->config = oss_config_create(options->pool);
    aos_str_set(&options->config->endpoint, endpoint);
    aos_str_set(&options->config->access_key_id, getenv("OSS_ACCESS_KEY_ID"));
    aos_str_set(&options->config->access_key_secret, getenv("OSS_ACCESS_KEY_SECRET"));
    aos_str_set(&options->config->region, region);
    options->config->signature_version = 4;
    options->config->is_cname = 0;
    options->ctl = aos_http_controller_create(options->pool, 0);
}

int main(int argc, char *argv[])
{
    if (aos_http_io_initialize(NULL, 0) != AOSE_OK) {
        exit(1);
    }

    aos_pool_t *pool;
    aos_pool_create(&pool, NULL);

    oss_request_options_t *oss_client_options = oss_request_options_create(pool);
    init_options(oss_client_options);

    aos_string_t source_bucket, source_object, dest_bucket, dest_object;
    aos_table_t *headers = NULL, *resp_headers = NULL;
    aos_status_t *resp_status = NULL;

    aos_str_set(&source_bucket, source_bucket_name);
    aos_str_set(&source_object, source_object_name);
    aos_str_set(&dest_bucket, dest_bucket_name);
    aos_str_set(&dest_object, dest_object_name);
    headers = aos_table_make(pool, 0);

    resp_status = oss_copy_object(oss_client_options,
        &source_bucket, &source_object,
        &dest_bucket, &dest_object,
        headers, &resp_headers);

    if (aos_status_is_ok(resp_status)) {
        printf("copy object succeeded\n");
    } else {
        printf("copy object failed\n");
    }

    aos_pool_destroy(pool);
    aos_http_io_deinitialize();
    return 0;
}

</details>

ossutil の使用

srcObjectsrcBucket から examplebucket にコピーします。

ossutil api copy-object --bucket examplebucket --key exampleobject --copy-source /srcBucket/srcObject

インストール手順については、「ossutil のインストール」をご参照ください。完全なパラメーターリファレンスについては、「copy-object」をご参照ください。

CopyObject API を直接使用

上記の方法はすべて、CopyObject API オペレーションに基づいています。テストケースでカスタムリクエストの構築が必要な場合は、API を直接呼び出します。直接の API 呼び出しでは、コード内で署名計算が必要です。

次のステップ

  • 1 GB を超えるオブジェクトをコピーするには、UploadPartCopy 操作を使用します。「概要」をご参照ください。

  • 意図しない上書きからオブジェクトを保護するには、送信先バケットでバージョン管理を有効にします。

  • コピー後にストレージコストを管理するには、オブジェクトを低コストのストレージクラスに自動的にトランジションするようにライフサイクルルールを設定します。