このトピックでは、同一リージョン内のバケット内またはバケット間でオブジェクトをコピーする方法について説明します。
注意事項
このトピックでは、中国 (杭州) リージョンのパブリックエンドポイントを使用します。Object Storage Service (OSS) と同じリージョンにある他の Alibaba Cloud サービスから OSS にアクセスする場合は、内部エンドポイントを使用してください。OSS のリージョンとエンドポイントの詳細については、リージョンとエンドポイントをご参照ください。
このトピックでは、アクセス認証情報は環境変数から取得されます。アクセス認証情報の設定方法の詳細については、OSS SDK for Python 1.0 を使用したアクセス認証情報の設定をご参照ください。
このトピックでは、OSS エンドポイントを使用して OSSClient インスタンスを作成します。カスタムドメイン名またはセキュリティトークンサービス (STS) を使用して OSSClient インスタンスを作成する場合は、初期化をご参照ください。
オブジェクトをコピーするには、ソースオブジェクトに対する読み取り権限と、コピー先バケットに対する読み取りおよび書き込み権限が必要です。
ソースバケットとコピー先バケットに保持ポリシーが設定されていないことを確認してください。設定されている場合、The object you specified is immutable. というエラーメッセージが返されます。
ソースバケットとコピー先バケットは、同じリージョンにある必要があります。たとえば、中国 (杭州) リージョンにあるバケットから中国 (青島) リージョンにある別のバケットにオブジェクトをコピーすることはできません。
スモールオブジェクトのコピー
サイズが 1 GB 未満のオブジェクトをコピーするには、シンプルコピーを使用できます。次のコードは、シンプルコピーを使用して、srcexamplebucket バケットから srcexampleobject.txt という名前のオブジェクトを、destexamplebucket の destexampleobject.txt という名前のオブジェクトにコピーする方法の例を示しています。
# -*- coding: utf-8 -*-
import oss2
from oss2.credentials import EnvironmentVariableCredentialsProvider
# 環境変数からアクセス認証情報を取得します。サンプルコードを実行する前に、OSS_ACCESS_KEY_ID および OSS_ACCESS_KEY_SECRET 環境変数が設定されていることを確認してください。
auth = oss2.ProviderAuthV4(EnvironmentVariableCredentialsProvider())
# ソースバケットの名前を指定します。例:srcexamplebucket。
src_bucket_name = 'srcexamplebucket'
# コピー先バケットの名前を指定します。コピー先バケットは、ソースバケットと同じリージョンにある必要があります。例:destexamplebucket。
# バケット内でオブジェクトをコピーする場合は、ソースバケットとコピー先バケットに同じバケット名を指定してください。
dest_bucket_name = 'destexamplebucket'
# バケットが配置されているリージョンのエンドポイントを指定します。たとえば、バケットが中国 (杭州) リージョンにある場合、エンドポイントを https://oss-cn-hangzhou.aliyuncs.com に設定します。
endpoint = "https://oss-cn-hangzhou.aliyuncs.com"
# エンドポイントにマッピングされるリージョンの ID を指定します。例:cn-hangzhou。このパラメーターは、署名アルゴリズム V4 を使用する場合に必要です。
region = "cn-hangzhou"
bucket = oss2.Bucket(auth, endpoint, dest_bucket_name, region=region)
# ソースオブジェクトの完全なパスを指定します。完全なパスにバケット名を含めないでください。例:srcexampleobject.txt。
src_object_name = 'srcexampleobject.txt'
# コピー先オブジェクトの完全なパスを指定します。完全なパスにバケット名を含めないでください。例:destexampleobject.txt。
dest_object_name = 'destexampleobject.txt'
# headers = dict()
# CopyObject 操作が同名のオブジェクトを上書きするかどうかを指定します。この例では、このパラメーターは true に設定されており、同名のオブジェクトを上書きしないことを指定します。
# headers['x-oss-forbid-overwrite'] = 'true'
# ソースオブジェクトのパスを指定します。
# headers[OSS_COPY_OBJECT_SOURCE] = '/example-bucket-by-util/recode-test.txt'
# ソースオブジェクトの ETag 値がリクエストで指定された ETag 値と同じ場合、OSS はオブジェクトをコピーし、200 OK を返します。
# headers['x-oss-copy-source-if-match'] = '5B3C1A2E053D763E1B002CC607C5****'
# ソースオブジェクトの ETag 値がリクエストで指定された ETag 値と異なる場合、OSS はオブジェクトをコピーし、200 OK を返します。
# headers['x-oss-copy-source-if-none-match'] = '5B3C1A2E053D763E1B002CC607C5****'
# リクエストで指定された時刻がオブジェクトの実際の変更時刻と同じかそれ以降の場合、OSS はオブジェクトをコピーし、200 OK を返します。
# headers['x-oss-copy-source-if-unmodified-since'] = '2021-12-09T07:01:56.000Z'
# ソースオブジェクトがリクエストで指定された時刻以降に変更された場合、OSS はオブジェクトをコピーします。
# headers['x-oss-copy-source-if-modified-since'] = '2021-12-09T07:01:56.000Z'
# コピー先オブジェクトのメタデータの設定方法を指定します。メソッドを COPY に設定すると、ソースオブジェクトのメタデータがコピー先オブジェクトにコピーされます。
# headers[OSS_METADATA_DIRECTIVE] = 'COPY'
# OSS がコピー先オブジェクトを作成する際に、コピー先オブジェクトを暗号化するために使用されるサーバ側暗号化アルゴリズムを指定します。
# headers[OSS_SERVER_SIDE_ENCRYPTION] = 'KMS'
# Key Management Service (KMS) によって管理されるカスタマーマスターキー (CMK) を指定します。このパラメーターは、x-oss-server-side-encryption が KMS に設定されている場合にのみ有効です。
# headers['x-oss-server-side-encryption-key-id'] = '9468da86-3509-4f8d-a61e-6eab1eac****'
# コピー先オブジェクトのアクセス制御リスト (ACL) を指定します。この例では、このパラメーターは OBJECT_ACL_PRIVATE に設定されており、オブジェクト所有者と承認されたユーザーのみがオブジェクトに対する読み取りおよび書き込み権限を持つことを示します。
# headers[OSS_OBJECT_ACL] = oss2.OBJECT_ACL_PRIVATE
# コピー先オブジェクトのストレージクラスを指定します。この例では、ストレージクラスは Standard に設定されています。
# headers['x-oss-storage-class'] = oss2.BUCKET_STORAGE_CLASS_STANDARD
# オブジェクトのタグを指定します。オブジェクトに複数のタグを同時に指定できます。
# headers[OSS_OBJECT_TAGGING] = 'k1=v1&k2=v2&k3=v3'
# コピー先オブジェクトのタグの設定方法を指定します。メソッドを COPY に設定すると、ソースオブジェクトのタグがコピー先オブジェクトにコピーされます。
# headers[OSS_OBJECT_TAGGING_COPY_DIRECTIVE] = 'COPY'
# result = bucket.copy_object(src_bucket_name, src_object_name, dest_object_name, headers=headers)
# ソースバケットからコピー先バケットにオブジェクトをコピーします。
result = bucket.copy_object(src_bucket_name, src_object_name, dest_object_name)
# 応答を表示します。HTTP ステータスコード 200 が返された場合、操作は成功です。
print('result.status:', result.status)ラージオブジェクトのコピー
サイズが 1 GB を超えるオブジェクトをコピーするには、オブジェクトをパートに分割し、UploadPartCopy を使用してパートを順番にコピーする必要があります。マルチパートコピーを実装するには、次の手順を実行します。
bucket.init_multipart_upload を使用して、マルチパートコピータスクを開始します。
bucket.upload_part_copy を使用して、パートをコピーします。最後のパートを除き、各パートのサイズは 100 KB より大きくする必要があります。
bucket.complete_multipart_upload を使用して、マルチパートコピータスクを完了します。
次のコードは、マルチパートコピーを使用して、srcexamplebucket バケットから srcexampleobject.txt という名前のオブジェクトを、destexamplebucket の destexampleobject.txt という名前のオブジェクトにコピーする方法の例を示しています。
# -*- coding: utf-8 -*-
import oss2
from oss2.credentials import EnvironmentVariableCredentialsProvider
from oss2.models import PartInfo
from oss2 import determine_part_size
# 環境変数からアクセス認証情報を取得します。サンプルコードを実行する前に、OSS_ACCESS_KEY_ID および OSS_ACCESS_KEY_SECRET 環境変数が設定されていることを確認してください。
auth = oss2.ProviderAuthV4(EnvironmentVariableCredentialsProvider())
# ソースバケットの名前を指定します。例:srcexamplebucket。
src_bucket_name = 'srcexamplebucket'
# コピー先バケットの名前を指定します。コピー先バケットは、ソースバケットと同じリージョンにある必要があります。例:destexamplebucket。
# バケット内でオブジェクトをコピーする場合は、ソースバケットとコピー先バケットに同じバケット名を指定してください。
dest_bucket_name = 'destexamplebucket'
# バケットが配置されているリージョンのエンドポイントを指定します。たとえば、バケットが中国 (杭州) リージョンにある場合、エンドポイントを https://oss-cn-hangzhou.aliyuncs.com に設定します。
endpoint = "https://oss-cn-hangzhou.aliyuncs.com"
# エンドポイントにマッピングされるリージョンの ID を指定します。例:cn-hangzhou。このパラメーターは、署名アルゴリズム V4 を使用する場合に必要です。
region = "cn-hangzhou"
# バケット内でオブジェクトをコピーする場合は、このコード行をコメントアウトし、src_bucket を bucket に変更します。
bucket = oss2.Bucket(auth, endpoint, dest_bucket_name, region=region)
src_bucket = oss2.Bucket(auth, endpoint, src_bucket_name, region=region)
# ソースオブジェクトの完全なパスを指定します。完全なパスにバケット名を含めないでください。例:srcexampleobject.txt。
src_object_name = 'srcexampleobject.txt'
# コピー先オブジェクトの完全なパスを指定します。完全なパスにバケット名を含めないでください。例:destexampleobject.txt。
dest_object_name = 'destexampleobject.txt'
# ソースオブジェクトのサイズを取得します。バケット内でオブジェクトをコピーする場合は、src_bucket を bucket に変更します。
head_info = src_bucket.head_object(src_object_name)
total_size = head_info.content_length
print('src object size:', total_size)
# determine_part_size メソッドを使用してパートサイズを決定します。
part_size = determine_part_size(total_size, preferred_size=100 * 1024)
print('part_size:', part_size)
# マルチパートアップロードタスクを開始します。
upload_id = bucket.init_multipart_upload(dest_object_name).upload_id
parts = []
# パートをアップロードします。
part_number = 1
offset = 0
while offset < total_size:
num_to_upload = min(part_size, total_size - offset)
end = offset + num_to_upload - 1
# headers = dict()
# ソースオブジェクトのパスを指定します。
# headers[OSS_COPY_OBJECT_SOURCE] = '/example-bucket-by-util/recode-test.txt'
# コピーしたいデータの範囲を指定します。たとえば、bytes を 0~1023 に設定すると、ソースオブジェクトの最初の 1024 バイトがコピーされます。
# headers[OSS_COPY_OBJECT_SOURCE_RANGE] = 'bytes=0~1023'
# ソースオブジェクトの ETag 値がリクエストで指定された ETag 値と同じ場合、OSS はオブジェクトをコピーし、200 OK を返します。
# headers['x-oss-copy-source-if-match'] = '5B3C1A2E053D763E1B002CC6****'
# ソースオブジェクトの ETag 値がリクエストで指定された ETag 値と異なる場合、OSS はオブジェクトをコピーし、200 OK を返します。
# headers['x-oss-copy-source-if-none-match'] = '5B3C1A2E053D763E1B002CC6****'
# リクエストで指定された時刻がオブジェクトの実際の変更時刻と同じかそれ以降の場合、OSS はオブジェクトをコピーし、200 OK を返します。
# headers['x-oss-copy-source-if-unmodified-since'] = '2021-12-09T07:01:56.000Z'
# リクエストで指定された時刻がオブジェクトの実際の変更時刻より前の場合、OSS はオブジェクトをコピーし、200 OK を返します。
# headers['x-oss-copy-source-if-modified-since'] = '2021-12-09T07:01:56.000Z'
# result = bucket.upload_part_copy(src_bucket_name, src_object_name, (offset, end), dest_object_name, upload_id, part_number, headers=headers)
result = bucket.upload_part_copy(src_bucket_name, src_object_name, (offset, end), dest_object_name, upload_id, part_number)
# パート情報を保存します。
parts.append(PartInfo(part_number, result.etag))
offset += num_to_upload
part_number += 1
# マルチパートコピータスクを完了します。
result = bucket.complete_multipart_upload(dest_object_name, upload_id, parts)
# 返された応答の HTTP ステータスコードを表示します。
print('result :', result.status)
# オブジェクトのメタデータをクエリします。
head_info = bucket.head_object(dest_object_name)
# コピー先オブジェクトのサイズをクエリします。
dest_object_size = head_info.content_length
print('dest object size:', dest_object_size)
# ソースオブジェクトとコピー先オブジェクトのサイズを比較します。
assert dest_object_size == total_sizeリファレンス
スモールオブジェクトのコピー
スモールオブジェクトのコピーに使用される完全なサンプルコードについては、GitHub をご参照ください。
スモールオブジェクトのコピーに呼び出すことができる API 操作の詳細については、CopyObject をご参照ください。
ラージオブジェクトのコピー
ラージオブジェクトのコピーに呼び出すことができる API 操作の詳細については、UploadPartCopy をご参照ください。