This topic describes how to copy files (objects) in a versioning-enabled bucket. To copy files smaller than 1 GB, use the CopyObject method. To copy files larger than 1 GB, use the multipart copy (UploadPartCopy) method.
Usage notes
In this topic, the public endpoint of the China (Hangzhou) region is used. If you want to access OSS from other Alibaba Cloud services in the same region as OSS, use an internal endpoint. For more information about OSS regions and endpoints, 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:GetObjectandoss:PutObjectpermissions. For more information, see Attach a custom policy to a RAM user.
Copy small files
For files smaller than 1 GB, use the CopyObject method to copy a file from a source bucket to a destination bucket in the same region.
By default, `x-oss-copy-source` copies the current version of an object. If the current version is a delete marker, OSS returns a 404 error that indicates the object does not exist. Add a versionId to `x-oss-copy-source` to copy a specific version of the object. Delete markers cannot be copied.
You can restore an earlier version of an object by copying it to the same bucket. The copied version becomes the new current version.
If versioning is enabled for the destination bucket, OSS automatically generates a unique version ID for the newly copied object. This version ID is returned in the `x-oss-version-id` response header. If versioning is disabled or suspended for the destination bucket, OSS assigns a null version ID to the newly copied object. This action overwrites any existing object that has a null version ID.
You can copy appendable objects if versioning is disabled for the destination bucket. You cannot copy appendable objects if versioning is enabled or suspended for the destination bucket.
# -*- 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 set.
auth = oss2.ProviderAuthV4(EnvironmentVariableCredentialsProvider())
# Specify the name of the source bucket. Example: srcexamplebucket.
src_bucket_name = 'srcexamplebucket'
# Specify the name of the destination bucket, which must be in the same region as the source bucket. Example: destexamplebucket.
# If you copy a file within the same bucket, make sure that the source and destination bucket names are the same.
dest_bucket_name = 'destexamplebucket'
# Specify the endpoint for the region where the bucket is located. For example, if the bucket is in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com.
endpoint = "https://oss-cn-hangzhou.aliyuncs.com"
# Specify the region where the endpoint is located. Example: cn-hangzhou. Note that this parameter is required for V4 signatures.
region = "cn-hangzhou"
bucket = oss2.Bucket(auth, endpoint, dest_bucket_name, region=region)
# Specify the full path of the source object. The full path cannot contain the bucket name. Example: srcexampledir/exampleobject.txt.
src_object_name = 'srcexampledir/exampleobject.txt'
# Specify the full path of the destination object. The full path cannot contain the bucket name. Example: destexampledir/exampleobject.txt.
dest_object_name = 'destexampledir/exampleobject.txt'
# Specify the version ID of the object.
versionId = 'CAEQMxiBgICAof2D0BYiIDJhMGE3N2M1YTI1NDQzOGY5NTkyNTI3MGYyMzJm****'
# Copy the specified version of the file.
params = dict()
params['versionId'] = versionId
# Copy an object from the source bucket to the destination bucket.
result = bucket.copy_object(src_bucket_name, src_object_name, dest_object_name, params=params)
# View the status of the response. If the status code 200 is returned, the operation is successful.
print('result.status:', result.status)Copy large files
For files larger than 1 GB, use the multipart copy (UploadPartCopy) method.
By default, the UploadPartCopy operation copies a part from the current version of an existing object. To copy a part from a specific version of an object, add the versionId sub-resource to the `x-oss-copy-source` request header. For example: `x-oss-copy-source: /SourceBucketName/SourceObjectName?versionId=CAEQMxiBgICAof2D0BYiIDJhMGE3N2M1YTI1NDQzOGY5NTkyNTI3MGYyMzJm****`.
The `SourceObjectName` must be URL-encoded. The response returns the version ID of the source object in `x-oss-copy-source-version-id`.
If you do not specify a versionId, and the current version of the source object is a delete marker, OSS returns 404 Not Found. If you specify the versionId of a delete marker, OSS returns 400 Bad Request.
The following code shows how to perform a multipart copy.
# -*- 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 set.
auth = oss2.ProviderAuthV4(EnvironmentVariableCredentialsProvider())
# Specify the name of the source bucket. Example: srcexamplebucket.
src_bucket_name = 'srcexamplebucket'
# Specify the name of the destination bucket, which must be in the same region as the source bucket. Example: destexamplebucket.
# If you copy a file within the same bucket, make sure that the source and destination bucket names are the same.
dest_bucket_name = 'destexamplebucket'
# Specify the endpoint for the region where the bucket is located. For example, if the bucket is in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com.
endpoint = "https://oss-cn-hangzhou.aliyuncs.com"
# Specify the region where the endpoint is located. Example: cn-hangzhou. Note that this parameter is required for V4 signatures.
region = "cn-hangzhou"
bucket = oss2.Bucket(auth, endpoint, dest_bucket_name, region=region)
# If you copy a file within the same bucket, comment out this line and change src_bucket to bucket in the following code.
src_bucket = oss2.Bucket(auth, endpoint, src_bucket_name, region=region)
# Specify the full path of the source object. The full path cannot contain the bucket name. Example: srcexampledir/exampleobject.txt.
src_object_name = 'srcexampledir/exampleobject.txt'
# Specify the full path of the destination object. The full path cannot contain the bucket name. Example: destexampledir/exampleobject.txt.
dest_object_name = 'destexampledir/exampleobject.txt'
# Specify the version ID of the object.
versionId = 'CAEQQhiBgMC5kZDE4RciIGZmNzdlYzRjYzRkODQwYjQ5ZDE0Njg5MWM0ODQzNDg3'
params = dict()
params['versionId'] = versionId
# Obtain the size of the specified version of the source file. If you copy a file within the same 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)
# The determine_part_size method is used 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.
upload_id = bucket.init_multipart_upload(dest_object_name).upload_id
parts = []
# Upload parts one by one.
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.
result = bucket.complete_multipart_upload(dest_object_name, upload_id, parts)
# View the versionId of the destination object generated by the copy operation.
print('result version id:', result.versionid)
# Obtain the file metadata.
head_info = bucket.head_object(dest_object_name)
# View the size of the destination object.
dest_object_size = head_info.content_length
print('dest object size:', dest_object_size)
# Compare the sizes of the source and destination objects.
assert dest_object_size == total_sizeReferences
For more information about copying small files, see CopyObject.
For more information about copying large files, see UploadPartCopy.