このトピックでは、OSS SDK for Python 2.0 の UploadPartCopy メソッドを使用して、ソースバケット内のオブジェクトからパートをコピーし、それらを宛先バケット内の新しい完全なオブジェクトにアセンブルする方法について説明します。ソースバケットと宛先バケットは同じでも異なっていてもかまいませんが、同じリージョンにある必要があります。
使用上の注意
このトピックのサンプルコードでは、中国 (杭州) リージョンのリージョン ID
cn-hangzhouを使用します。デフォルトでは、パブリックエンドポイントを使用してバケット内のリソースにアクセスします。バケットが配置されているのと同じリージョン内の他の Alibaba Cloud サービスからバケット内のリソースにアクセスする場合は、内部エンドポイントを使用します。OSS がサポートするリージョンとエンドポイントの詳細については、「リージョンとエンドポイント」をご参照ください。オブジェクトをコピーするには、ソースオブジェクトに対する読み取り権限と、宛先バケットに対する読み取りおよび書き込み権限が必要です。
ソースバケットと宛先バケットは、同じリージョンに配置する必要があります。たとえば、中国 (杭州) リージョンにあるバケット内のオブジェクトを、中国 (青島) リージョンにあるバケットにコピーすることはできません。
ソースバケットと宛先バケットにリテンションポリシーが設定されていないことを確認してください。設定されている場合、次のエラーメッセージが返されます: The object you specified is immutable.
メソッド
upload_part_copy(request: UploadPartCopyRequest, **kwargs) → UploadPartCopyResultリクエストパラメーター
パラメーター | タイプ | 説明 |
request | UploadPartCopyRequest | リクエストパラメーター。詳細については、「UploadPartCopyRequest」をご参照ください。 |
レスポンスパラメーター
タイプ | 説明 |
UploadPartCopyResult | 戻り値。詳細については、「UploadPartCopyResult」をご参照ください。 |
マルチパートコピーメソッドの完全な定義については、「upload_part_copy」をご参照ください。
マルチパートコピーのプロセス
マルチパートアップロードを使用してローカルファイルをアップロードするには、次の手順を実行します:
マルチパートアップロードタスクを開始します。
OSS で一意のアップロード ID を取得するには、client.initiate_multipart_upload メソッドを使用します。
パートをアップロードします。
OSS で一意のアップロード ID を取得するには、client.upload_part_copy メソッドを使用します。
説明特定のアップロード ID を持つマルチパートアップロードタスクを実行してアップロードされたパートの場合、パート番号はオブジェクト内の相対的な位置を識別します。パートをアップロードし、そのパート番号を再利用して別のパートをアップロードすると、新しいパートが元のパートを上書きします。
OSS は、パートデータの MD5 ハッシュを ETag ヘッダーに含め、その MD5 ハッシュをユーザーに返します。
OSS は、アップロードされたパートの MD5 ハッシュを計算し、その MD5 ハッシュを OSS SDK for Harmony を使用して計算された MD5 ハッシュと比較します。2 つのハッシュが異なる場合、OSS は InvalidDigest エラーコードを返します。
マルチパートアップロードタスクを完了します。
client.complete_multipart_upload メソッドを使用して、アップロードされたパートをオブジェクトに結合します。
サンプルコード
次のサンプルコードは、マルチパートコピーを使用してソースバケットから宛先バケットにオブジェクトをコピーし、パートを結合して完全なオブジェクトにする方法の例を示しています:
import argparse
import alibabacloud_oss_v2 as oss
# コマンドライン引数パーサーを作成し、スクリプトの目的を記述します: 同期マルチパートコピーとアップロードのサンプル
parser = argparse.ArgumentParser(description="upload part copy synchronously sample")
# バケットが配置されているリージョンを示す --region コマンドラインパラメーターを追加します。このパラメーターは必須です。
parser.add_argument('--region', help='The region in which the bucket is located.', required=True)
# オブジェクトのアップロード先となる宛先バケットの名前を示す --bucket コマンドラインパラメーターを追加します。このパラメーターは必須です。
parser.add_argument('--bucket', help='The name of the bucket.', required=True)
# 他のサービスが OSS にアクセスするために使用できるドメイン名を示す --endpoint コマンドラインパラメーターを追加します。このパラメーターはオプションです。
parser.add_argument('--endpoint', help='The domain names that other services can use to access OSS')
# OSS 内の宛先オブジェクトのキーを示す --key コマンドラインパラメーターを追加します。このパラメーターは必須です。
parser.add_argument('--key', help='The name of the object.', required=True)
# ソースオブジェクトが配置されているバケットの名前を示す --source_bucket コマンドラインパラメーターを追加します。このパラメーターは必須です。
parser.add_argument('--source_bucket', help='The name of the source bucket.', required=True)
# OSS 内のソースオブジェクトのキーを示す --source_key コマンドラインパラメーターを追加します。このパラメーターは必須です。
parser.add_argument('--source_key', help='The name of the source object.', required=True)
def main():
# コマンドラインで提供されたパラメーターを解析して、ユーザーが入力した値を取得します。
args = parser.parse_args()
# ID 検証のために、環境変数から OSS へのアクセスに必要な認証情報を読み込みます。
credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()
# SDK のデフォルト構成を使用して構成オブジェクトを作成し、認証プロバイダーを設定します。
cfg = oss.config.load_default()
cfg.credentials_provider = credentials_provider
cfg.region = args.region
# カスタムエンドポイントが提供されている場合は、構成オブジェクトのエンドポイントプロパティを更新します。
if args.endpoint is not None:
cfg.endpoint = args.endpoint
# 上記の構成を使用して OSS クライアントを初期化し、OSS との対話の準備をします。
client = oss.Client(cfg)
# ソースオブジェクトのメタデータを取得します。
result_meta = client.get_object_meta(oss.GetObjectMetaRequest(
bucket=args.source_bucket,
key=args.source_key,
))
# マルチパートアップロードリクエストを初期化し、プロセスを識別するためのアップロード ID を返します。
result = client.initiate_multipart_upload(oss.InitiateMultipartUploadRequest(
bucket=args.bucket,
key=args.key,
))
# 各パートのサイズを定義します。この例では、サイズは 1 MB に設定されています。
part_size = 1024 * 1024
total_size = result_meta.content_length # ソースファイルの合計サイズ。
part_number = 1 # パート番号は 1 から始まります。
upload_parts = [] # アップロードされたパートの情報を格納するために使用されます。
offset = 0 # 現在のバイトオフセット。
# すべてのデータがアップロードされるまでループします。
while offset < total_size:
num_to_upload = min(part_size, total_size - offset) # 今回アップロードするデータ量を計算します。
end = offset + num_to_upload - 1 # 終了位置を決定します。
# 実際のマルチパートコピーとアップロード操作を実行します。
up_result = client.upload_part_copy(oss.UploadPartCopyRequest(
bucket=args.bucket,
key=args.key,
upload_id=result.upload_id,
part_number=part_number,
source_bucket=args.source_bucket,
source_key=args.source_key,
source_range=f'bytes={offset}-{end}', # ソースオブジェクト内の範囲を指定します。
))
# アップロードされたパートのステータス情報を出力します。
print(f'status code: {up_result.status_code},'
f' request id: {up_result.request_id},'
f' part number: {part_number},'
f' last modified: {up_result.last_modified},'
f' etag: {up_result.etag},'
f' source version id: {up_result.source_version_id}'
)
# 正常にアップロードされたパートの情報を記録します。
upload_parts.append(oss.UploadPart(part_number=part_number, etag=up_result.etag))
offset += num_to_upload # オフセットを更新します。
part_number += 1 # パート番号を更新します。
# アップロードされたすべてのパートをパート番号でソートします。
parts = sorted(upload_parts, key=lambda p: p.part_number)
# OSS サービスにリクエストを送信して、マルチパートアップロードを完了します。
result = client.complete_multipart_upload(oss.CompleteMultipartUploadRequest(
bucket=args.bucket,
key=args.key,
upload_id=result.upload_id,
complete_multipart_upload=oss.CompleteMultipartUpload(
parts=parts
)
))
# アップロード完了後の詳細な結果を出力します。
print(f'status code: {result.status_code},'
f' request id: {result.request_id},'
f' bucket: {result.bucket},'
f' key: {result.key},'
f' location: {result.location},'
f' etag: {result.etag},'
f' encoding type: {result.encoding_type},'
f' hash crc64: {result.hash_crc64},'
f' version id: {result.version_id}'
)
# このスクリプトが直接実行される場合、main 関数を呼び出してロジックの処理を開始します。
if __name__ == "__main__":
main() # スクリプトのエントリポイント。プログラムのフローはここから始まります。リファレンス
マルチパートコピーの完全なサンプルコードについては、「upload_part_copy.py」をご参照ください。