Copy files (Python SDK V2)

更新时间:
复制 MD 格式

Use CopyObject to copy objects smaller than 1 GB, and UploadPartCopy to copy objects larger than 1 GB in a versioning-enabled bucket.

Prerequisites

Before you begin, ensure that you have:

  • The oss:GetObject and oss:PutObject permissions. For details, see Attach a custom policy to a RAM user

  • OSS SDK for Python V2 installed (alibabacloud_oss_v2)

  • Your AccessKey ID and AccessKey Secret configured as environment variables for oss.credentials.EnvironmentVariableCredentialsProvider()

Copy an object

CopyObject copies a source object to a destination bucket in the same region. Use this method for objects smaller than 1 GB.

Versioning behavior

By default, CopyObject copies the current version of the source object. Pass a source_version_id to copy a specific version instead.

ConditionResult
No version ID specified; current version is a delete markerOSS returns 404 Not Found
Version ID specifiedOSS copies that specific version
Delete marker specified as sourceNot supported — delete markers cannot be copied
Destination bucket has versioning enabledOSS assigns a unique version ID to the copied object, returned in the x-oss-version-id response header
Destination bucket has versioning disabled or suspendedOSS generates a null version ID and overwrites any previous null-version object
Source object is appendableCannot be copied to a versioning-enabled or versioning-suspended destination bucket
Copying an earlier version to the same bucket creates a new current version, effectively restoring that version.

Core API call

result = client.copy_object(oss.CopyObjectRequest(
    bucket="<destination-bucket>",
    key="<destination-object-key>",
    source_bucket="<source-bucket>",
    source_key="<source-object-key>",
    source_version_id="<source-version-id>",  # Omit to copy the current version
))
print(f"version ID: {result.version_id}, source version ID: {result.source_version_id}")

Full runnable example

The sample code below uses the cn-hangzhou region and a public endpoint. To access OSS from another Alibaba Cloud service in the same region, use an internal endpoint. For a list of regions and endpoints, see Regions and endpoints.

import argparse
import alibabacloud_oss_v2 as oss

parser = argparse.ArgumentParser(description="copy object sample")
parser.add_argument('--region', required=True, help='Region where the bucket is located.')
parser.add_argument('--bucket', required=True, help='Destination bucket name.')
parser.add_argument('--endpoint', help='Custom endpoint (optional).')
parser.add_argument('--key', required=True, help='Destination object key.')
parser.add_argument('--source_bucket', required=True, help='Source bucket name.')
parser.add_argument('--source_key', required=True, help='Source object key.')
parser.add_argument('--source_version_id', required=True, help='Version ID of the source object.')

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_bucket=args.source_bucket,
        source_key=args.source_key,
        source_version_id=args.source_version_id,
    ))

    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()

Multipart copy

For objects larger than 1 GB, use UploadPartCopy. This method requires you to manage the full multipart workflow manually. The process involves four steps:

  1. Get the source object size using GetObjectMeta.

  2. Initiate a multipart upload with InitiateMultipartUpload to get an upload ID.

  3. Split the object into parts and copy each part with UploadPartCopy, specifying a byte range.

  4. Complete the upload with CompleteMultipartUpload after all parts are copied.

Versioning behavior

By default, UploadPartCopy copies a part from the current version of the source object. Pass a source_version_id to copy from a specific version.

ConditionResult
No version ID specified; current version is a delete markerOSS returns 404 Not Found
Version ID specified and corresponds to a delete markerOSS returns 400 Bad Request

Full runnable example

import argparse
import alibabacloud_oss_v2 as oss

parser = argparse.ArgumentParser(description="upload part copy synchronously sample")
parser.add_argument('--region', required=True, help='Region where the bucket is located.')
parser.add_argument('--bucket', required=True, help='Destination bucket name.')
parser.add_argument('--endpoint', help='Custom endpoint (optional).')
parser.add_argument('--key', required=True, help='Destination object key.')
parser.add_argument('--source_bucket', required=True, help='Source bucket name.')
parser.add_argument('--source_key', required=True, help='Source object key.')
parser.add_argument('--source_version_id', required=True, help='Version ID of the source object.')

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)

    # Step 1: Get the source object size
    result_meta = client.get_object_meta(oss.GetObjectMetaRequest(
        bucket=args.source_bucket,
        key=args.source_key,
    ))

    # Step 2: Initiate a multipart upload
    result = client.initiate_multipart_upload(oss.InitiateMultipartUploadRequest(
        bucket=args.bucket,
        key=args.key,
    ))

    # Step 3: Copy each part
    part_size = 1024 * 1024  # 1 MB per part
    total_size = result_meta.content_length
    part_number = 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_version_id=args.source_version_id,
            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

    # Step 4: Complete the multipart upload
    parts = sorted(upload_parts, key=lambda p: p.part_number)
    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},'
          )

if __name__ == "__main__":
    main()

References