All Products
Search
Document Center

Object Storage Service:Copy objects

Last Updated:Oct 16, 2023

This topic describes how to copy an object in a versioning-enabled bucket in Object Storage Service (OSS). You can call CopyObject to copy an object that is up to 1 GB in size and call UploadPartCopy to copy an object that is larger than 1 GB.

Usage notes

  • In this topic, the public endpoint of the China (Hangzhou) region is used. If you want to access OSS by using other Alibaba Cloud services in the same region as OSS, use an internal endpoint. For more information about the regions and endpoints supported by OSS, see Regions and endpoints.

  • In this topic, an OSSClient instance is created by using an OSS endpoint. If you want to create an OSSClient instance by using custom domain names or Security Token Service (STS), see Initialization.

  • To copy an object, you must have the oss:GetObject and oss:PutObject permissions. For more information, see Attach a custom policy to a RAM user.

Copy a small object

You can call CopyObject to copy an object that is up to 1 GB in size from a source bucket to a destination bucket within the same region.

  • By default, the x-oss-copy-source header in a CopyObject request specifies the current version of the object that you want to copy. If the current version of the object is a delete marker, OSS returns HTTP status code 404, which indicates that the object does not exist. You can add a version ID to the x-oss-copy-source header to copy the specified object version. Delete markers cannot be copied.

  • You can copy a previous version of an object to the same bucket. The copied previous version becomes the current version of the object. This way, the previous version of the object is recovered as the latest version.

  • If versioning is enabled for the destination bucket, OSS generates a unique version ID for the destination object. The version ID is returned as the value of the x-oss-version-id header in the response. If versioning is not enabled or is suspended for the destination bucket, OSS generates a version whose version ID is null for the destination object and the generated version overwrites the original version whose version ID is null.

  • If versioning is not enabled for the destination bucket, you can copy appendable objects. If versioning is enabled or suspended for the destination bucket, you cannot copy appendable objects.

# -*- coding: utf-8 -*-
import oss2
from oss2.credentials import EnvironmentVariableCredentialsProvider

# 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. 
auth = oss2.ProviderAuth(EnvironmentVariableCredentialsProvider())
# Specify the name of the source bucket. Example: srcexamplebucket. 
src_bucket_name = 'srcexamplebucket'
# Specify the name of the destination bucket. The destination bucket must be in the same region as the source bucket. Example: destexamplebucket. 
# If you copy an object within a bucket, make sure that you specify the same bucket name for the source and destination buckets. 
dest_bucket_name = 'destexamplebucket'
# Specify the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com. 
bucket = oss2.Bucket(auth, 'https://oss-cn-hangzhou.aliyuncs.com', dest_bucket_name)

# Specify the full path of the source object. Do not include the bucket name in the full path. Example: exampledir/exampleobject.txt. 
src_object_name = 'srcexampledir/exampleobject.txt'
# Specify the full path of the destination object. Do not include the bucket name in the full path. Example: exampledir/exampleobject.txt. 
dest_object_name = 'destexampledir/exampleobject.txt'
# Specify the version ID of the object. 
versionId = 'CAEQMxiBgICAof2D0BYiIDJhMGE3N2M1YTI1NDQzOGY5NTkyNTI3MGYyMzJm****'

# Copy the specified version of the source object. 
params = dict()
params['versionId'] = versionId

# Copy the source object from the source bucket to the destination bucket. 
result = bucket.copy_object(src_bucket_name, src_object_name, dest_object_name, params=params)
# Display the response. If the returned value is 200, the source object is copied to the destination bucket. 
print('result.status:', result.status)

Copy a large object

To copy an object that is larger than 1 GB in size, you need to split the object into parts and copy the parts by using UploadPartCopy.

By default, the UploadPartCopy operation uploads a part by copying data from the current version of the specified object. You can add a version ID to the x-oss-copy-source header to copy the specified version of the object. Example: x-oss-copy-source: /SourceBucketName/SourceObjectName?versionId=CAEQMxiBgICAof2D0BYiIDJhMGE3N2M1YTI1NDQzOGY5NTkyNTI3MGYyMzJm****.

Note

The value of the SourceObjectName parameter must be URL-encoded. The version ID of the copied object is returned as the value of the x-oss-copy-source-version-id header in the response.

If a version ID is not specified in the request and the current version of the source object is a delete marker, OSS returns 404 Not Found. If a version ID is specified in the request and the specified version of the source object is a delete marker, OSS returns 400 Bad Request.

The following code provides an example on how to copy an object by using UploadPartCopy:

# -*- coding: utf-8 -*-
import os
import oss2
from oss2 import determine_part_size
from oss2.models import PartInfo
from oss2.credentials import EnvironmentVariableCredentialsProvider

# 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. 
auth = oss2.ProviderAuth(EnvironmentVariableCredentialsProvider())
# Specify the name of the source bucket. Example: srcexamplebucket. 
src_bucket_name = 'srcexamplebucket'
# Specify the name of the destination bucket. The destination bucket must be in the same region as the source bucket. Example: destexamplebucket. 
# If you copy an object within a bucket, make sure that you specify the same bucket name for the source and destination buckets. 
dest_bucket_name = 'destexamplebucket'
# Specify the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com. 
bucket = oss2.Bucket(auth, 'https://oss-cn-hangzhou.aliyuncs.com', dest_bucket_name)
# If you copy an object within a bucket, comment out this line of code and change src_bucket in src_bucket_name to bucket. 
src_bucket = oss2.Bucket(auth, 'https://oss-cn-hangzhou.aliyuncs.com', src_bucket_name)

# Specify the full path of the source object. Do not include the bucket name in the full path. Example: exampledir/exampleobject.txt. 
src_object_name = 'srcexampledir/exampleobject.txt'
# Specify the full path of the destination object. Do not include the bucket name in the full path. Example: exampledir/exampleobject.txt. 
dest_object_name = 'destexampledir/exampleobject.txt'
# Specify the version ID of the object. 
versionId = 'CAEQQhiBgMC5kZDE4RciIGZmNzdlYzRjYzRkODQwYjQ5ZDE0Njg5MWM0ODQzNDg3'

params = dict()
params['versionId'] = versionId

# Query the size of the specified version of the source object. If you copy an object within a bucket, change src_bucket to bucket. 
head_info = src_bucket.head_object(src_object_name, params=params)
total_size = head_info.content_length
print('src object size:', total_size)

# Use the determine_part_size method to determine the part size. 
part_size = determine_part_size(total_size, preferred_size=100 * 1024)
print('part_size:', part_size)

# Initiate a multipart upload task. 
upload_id = bucket.init_multipart_upload(dest_object_name).upload_id
parts = []

# Upload the 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
    result = bucket.upload_part_copy(src_bucket_name, src_object_name, (offset, end), dest_object_name, upload_id, part_number, params=params)
    # Save the part information. 
    parts.append(PartInfo(part_number, result.etag))

    offset += num_to_upload
    part_number += 1

# Complete the multipart upload task. 
result = bucket.complete_multipart_upload(dest_object_name, upload_id, parts)
# Display the version ID of the destination object. 
print('result version id:', result.versionid)
# Query the metadata of the object. 
head_info = bucket.head_object(dest_object_name)
# Query the size of the destination object. 
dest_object_size = head_info.content_length
print('dest object size:', dest_object_size)
# Compare the sizes between the source and destination objects. 
assert dest_object_size == total_size

References

  • For more information about how to copy a small object, see CopyObject.

  • For more information about how to copy a large object, see UploadPartCopy.