All Products
Search
Document Center

Object Storage Service:Copy objects in CloudBox

Last Updated:Sep 15, 2026

You can copy an object from a source OSS on CloudBox bucket to a destination OSS on CloudBox bucket in the same region without changing the object content. This process supports use cases such as data backup, distribution, and disaster recovery. It improves data availability and redundancy, and ensures data consistency and security between buckets. The destination bucket must be in the same region as the source bucket. CloudBox is an efficient and reliable data storage and management service from Alibaba Cloud.

Limits

You cannot copy objects across regions. For example, you cannot copy an object from a bucket in the China (Hangzhou) region to a bucket in the China (Shanghai) region.

Usage notes

  • You must have read permissions on the source object and read and write permissions on the destination bucket. Otherwise, the copy operation fails.

  • By default, copying an object overwrites an existing object with the same name in the destination bucket. To prevent objects from being accidentally overwritten, you can use one of the following methods:

    • Enable versioning

      Overwritten or deleted objects are saved as historical versions. You can restore them at any time. For more information, see Versioning for CloudBox.

    • Include a parameter that prohibits object overwrites in the copy request

      Include the x-oss-forbid-overwrite header in the copy request and set its value to true. If an object that has the same name as the object you want to copy exists in the destination bucket, the copy fails and the FileAlreadyExists error is returned.

Copy a small object

You can copy objects smaller than 1 GB in OSS on CloudBox by calling the CopyObject API operation.

Use an Alibaba Cloud SDK

You can copy objects by using the OSS SDK for Java, Python, or Go (Java SDK 3.15.0 or later, Python SDK V2 1.1.1 or later, or Go SDK V2 v1.2.1 or later). For OSS on CloudBox, the Python and Go SDKs are called in the same way as they are in public cloud OSS. For information about how to create a client, see SDK support. The following code examples use the Java, Python, and Go SDKs.

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.*;
import com.aliyun.oss.common.auth.DefaultCredentialProvider;
import com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.ClientBuilderConfiguration;
import com.aliyun.oss.common.auth.CredentialsProviderFactory;
import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;

public class Demo {
    public static void main(String[] args) throws Exception {
        // Specify the data endpoint of the OSS on CloudBox bucket.
        String endpoint = "https://cb-f8z7yvzgwfkl9q0h****.cn-hangzhou.oss-cloudbox.aliyuncs.com";
        // Obtain access credentials from environment variables. Before you run this sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are set.
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        // Specify the region where the source and destination OSS on CloudBox buckets are located.
        String region = "cn-hangzhou";
        // Specify the ID of the CloudBox.
        String cloudBoxId = "cb-f8z7yvzgwfkl9q0h****";
        // Specify the name of the source OSS on CloudBox bucket.
        String sourceBucketName = "srcexamplebucket";
        // Specify the full path of the source object. The full path cannot include the bucket name.
        String sourceKey = "srcexampleobject.txt";
        // Specify the name of the destination OSS on CloudBox bucket that is in the same region as the source bucket.
        String destinationBucketName = "desexamplebucket";
        // Specify the full path of the destination object. The full path cannot include the bucket name.
        String destinationKey = "desexampleobject.txt";

        // Create an OSSClient instance.
        // When the OSSClient instance is no longer used, call the shutdown method to release its resources.
        ClientBuilderConfiguration conf = new ClientBuilderConfiguration();
        conf.setSignatureVersion(SignVersion.V4);
        OSS ossClient = OSSClientBuilder.create()
                .endpoint(endpoint)
                .credentialsProvider(new DefaultCredentialProvider(credentialsProvider.getCredentials()))
                .clientConfiguration(conf)
                .region(region)
                .cloudBoxId(cloudBoxId)
                .build();

        try {
            // Create a CopyObjectRequest object.
            CopyObjectRequest copyObjectRequest = new CopyObjectRequest(sourceBucketName, sourceKey, destinationBucketName, destinationKey);

            // Set new object metadata.
            ObjectMetadata meta = new ObjectMetadata();
            meta.setContentType("text/txt");
            // Specify whether to overwrite the destination object if it has the same name. In this example, this parameter is set to true to prohibit overwriting.
            // meta.setHeader("x-oss-forbid-overwrite", "true");
            // Specify the source path for the copy operation.
            // meta.setHeader(OSSHeaders.COPY_OBJECT_SOURCE, "/examplebucket/recode-test.txt");
            // If the ETag of the source object matches the ETag you provide, the copy operation is performed and 200 OK is returned.
            // meta.setHeader(OSSHeaders.COPY_OBJECT_SOURCE_IF_MATCH, "5B3C1A2E053D763E1B002CC607C5****");
            // If the ETag of the source object does not match the ETag you provide, the copy operation is performed and 200 OK is returned.
            // meta.setHeader(OSSHeaders.COPY_OBJECT_SOURCE_IF_NONE_MATCH, "5B3C1A2E053D763E1B002CC607C5****");
            // If the specified time is the same as or later than the actual modification time of the object, the object is copied and 200 OK is returned.
            // meta.setHeader(OSSHeaders.COPY_OBJECT_SOURCE_IF_UNMODIFIED_SINCE, "2021-12-09T07:01:56.000Z");
            // If the source object was modified after the specified time, the copy operation is performed.
            // meta.setHeader(OSSHeaders.COPY_OBJECT_SOURCE_IF_MODIFIED_SINCE, "2021-12-09T07:01:56.000Z");
            // Specify how to set the metadata of the destination object. In this example, this parameter is set to COPY to copy the metadata from the source object to the destination object.
            // meta.setHeader(OSSHeaders.COPY_OBJECT_METADATA_DIRECTIVE, "COPY");
            // Specify the server-side encryption algorithm for OSS to use when creating the destination object.
            // meta.setHeader(OSSHeaders.OSS_SERVER_SIDE_ENCRYPTION, ObjectMetadata.KMS_SERVER_SIDE_ENCRYPTION);
            // Specify the customer master key (CMK) managed by KMS. This parameter is valid only when x-oss-server-side-encryption is set to KMS.
            // meta.setHeader(OSSHeaders.OSS_SERVER_SIDE_ENCRYPTION_KEY_ID, "9468da86-3509-4f8d-a61e-6eab1eac****");
            // Specify the access permissions for the destination object when it is created in OSS. In this example, this parameter is set to Private. This means only the object owner and authorized users have read and write permissions on the object. Other users cannot access the object.
            // meta.setHeader(OSSHeaders.OSS_OBJECT_ACL, CannedAccessControlList.Private);
            // Specify the storage class of the object. In this example, this parameter is set to Standard.
            // meta.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard);
            // Specify object tags. You can specify multiple tags at the same time.
            // meta.setHeader(OSSHeaders.OSS_TAGGING, "a:1");
            // Specify how to set tags for the destination object. In this example, this parameter is set to COPY to copy the tags from the source object to the destination object.
            // meta.setHeader(OSSHeaders.COPY_OBJECT_TAGGING_DIRECTIVE, "COPY");
            copyObjectRequest.setNewObjectMetadata(meta);

            // Copy the file.
            CopyObjectResult result = ossClient.copyObject(copyObjectRequest);
            System.out.println("ETag: " + result.getETag() + " LastModified: " + result.getLastModified());
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }
}
# -*- coding: utf-8 -*-
import alibabacloud_oss_v2 as oss

# Obtain access credentials from environment variables. Before running this code example, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are set.
credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()

# Use the default configuration of the SDK.
cfg = oss.config.load_default()
cfg.credentials_provider = credentials_provider

# Specify the region in which the CloudBox is located, such as cn-hangzhou.
cfg.region = "cn-hangzhou"

# Specify the CloudBox ID. After you set the CloudBox ID, the SDK automatically switches the signing product to oss-cloudbox.
cfg.cloud_box_id = "cb-f8z7yvzgwfkl9q0h****"

# Specify the data domain in the CloudboxId.Region.oss-cloudbox.aliyuncs.com format.
cfg.endpoint = "cb-f8z7yvzgwfkl9q0h****.cn-hangzhou.oss-cloudbox.aliyuncs.com"

# Create an OSS client.
client = oss.Client(cfg)

# Specify the name of the source CloudBox bucket, such as srcexamplebucket.
source_bucket_name = "srcexamplebucket"
# Specify the full path of the source object. The full path cannot contain the bucket name.
source_key = "srcexampleobject.txt"
# Specify the name of the destination CloudBox bucket, which must be in the same region as the source bucket, such as desexamplebucket.
dest_bucket_name = "desexamplebucket"
# Specify the full path of the destination object. The full path cannot contain the bucket name.
dest_key = "desexampleobject.txt"

# Copy the object.
result = client.copy_object(oss.CopyObjectRequest(
    bucket=dest_bucket_name,
    key=dest_key,
    source_bucket=source_bucket_name,
    source_key=source_key,
))
print(f'ETag: {result.etag}, LastModified: {result.last_modified}')
package main

import (
	"context"
	"log"

	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss"
	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials"
)

func main() {
	// Load the default configuration of the SDK and set the access credentials, region, CloudBox ID, and data domain.
	// Obtain access credentials from environment variables. Before running this code example, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are set.
	cfg := oss.LoadDefaultConfig().
		WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
		// Specify the region in which the CloudBox is located, such as cn-hangzhou.
		WithRegion("cn-hangzhou").
		// Specify the data domain in the CloudboxId.Region.oss-cloudbox.aliyuncs.com format.
		WithEndpoint("cb-f8z7yvzgwfkl9q0h****.cn-hangzhou.oss-cloudbox.aliyuncs.com").
		// Specify the CloudBox ID. After you set the CloudBox ID, the SDK automatically switches the signing product to oss-cloudbox.
		WithCloudBoxId("cb-f8z7yvzgwfkl9q0h****")

	// Create an OSS client.
	client := oss.NewClient(cfg)

	// Specify the name of the source CloudBox bucket, such as srcexamplebucket.
	sourceBucketName := "srcexamplebucket"
	// Specify the full path of the source object. The full path cannot contain the bucket name.
	sourceKey := "srcexampleobject.txt"
	// Specify the name of the destination CloudBox bucket, which must be in the same region as the source bucket, such as desexamplebucket.
	destBucketName := "desexamplebucket"
	// Specify the full path of the destination object. The full path cannot contain the bucket name.
	destKey := "desexampleobject.txt"

	// Copy the object.
	result, err := client.CopyObject(context.TODO(), &oss.CopyObjectRequest{
		Bucket:       oss.Ptr(destBucketName),
		Key:          oss.Ptr(destKey),
		SourceBucket: oss.Ptr(sourceBucketName),
		SourceKey:    oss.Ptr(sourceKey),
	})
	if err != nil {
		log.Fatalf("failed to copy object %v", err)
	}
	log.Printf("ETag: %v, LastModified: %v\n", oss.ToString(result.ETag), oss.ToTime(result.LastModified))
}

Use ossutil

For more information about using ossutil to copy small objects, see cp (Copy files).

Copy a large object

You can copy objects larger than 1 GB in OSS on CloudBox by calling the UploadPartCopy API operation.

Use an Alibaba Cloud SDK

You can copy objects by using the OSS SDK for Java, Python, or Go (Java SDK 3.15.0 or later, Python SDK V2 1.1.1 or later, or Go SDK V2 v1.2.1 or later). For OSS on CloudBox, the Python and Go SDKs are called in the same way as they are in public cloud OSS. For information about how to create a client, see SDK support. The following code examples use the Java, Python, and Go SDKs.

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.*;
import java.util.ArrayList;
import java.util.List;
import com.aliyun.oss.common.auth.DefaultCredentialProvider;
import com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.ClientBuilderConfiguration;
import com.aliyun.oss.common.auth.CredentialsProviderFactory;
import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;

public class Demo {
    public static void main(String[] args) throws Exception {
        // Specify the data endpoint of the OSS on CloudBox bucket.
        String endpoint = "https://cb-f8z7yvzgwfkl9q0h****.cn-hangzhou.oss-cloudbox.aliyuncs.com";
        // Obtain access credentials from environment variables. Before you run this sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are set.
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        // Specify the region where the source and destination OSS on CloudBox buckets are located.
        String region = "cn-hangzhou";
        // Specify the ID of the CloudBox.
        String cloudBoxId = "cb-f8z7yvzgwfkl9q0h****";
        // Specify the name of the source OSS on CloudBox bucket.
        String sourceBucketName = "srcexamplebucket";
        // Specify the full path of the source object. The full path cannot include the bucket name.
        String sourceKey = "srcexampleobject.txt";
        // Specify the name of the destination OSS on CloudBox bucket that is in the same region as the source bucket.
        String destinationBucketName = "desexamplebucket";
        // Specify the full path of the destination object. The full path cannot include the bucket name.
        String destinationKey = "desexampleobject.txt";

        // Create an OSSClient instance.
        // When the OSSClient instance is no longer used, call the shutdown method to release its resources.
        ClientBuilderConfiguration conf = new ClientBuilderConfiguration();
        conf.setSignatureVersion(SignVersion.V4);
        OSS ossClient = OSSClientBuilder.create()
                .endpoint(endpoint)
                .credentialsProvider(new DefaultCredentialProvider(credentialsProvider.getCredentials()))
                .clientConfiguration(conf)
                .region(region)
                .cloudBoxId(cloudBoxId)
                .build();

        try {
            ObjectMetadata objectMetadata = ossClient.getObjectMetadata(sourceBucketName, sourceKey);
            // Obtain the size of the file to be copied.
            long contentLength = objectMetadata.getContentLength();

            // Set the part size to 10 MB. The unit is byte.
            long partSize = 1024 * 1024 * 10;

            // Calculate the total number of parts.
            int partCount = (int) (contentLength / partSize);
            if (contentLength % partSize != 0) {
                partCount++;
            }
            System.out.println("total part count:" + partCount);

            // Initialize the copy task. You can specify the metadata of the destination object using InitiateMultipartUploadRequest.
            InitiateMultipartUploadRequest initiateMultipartUploadRequest = new InitiateMultipartUploadRequest(destinationBucketName, destinationKey);
            InitiateMultipartUploadResult initiateMultipartUploadResult = ossClient.initiateMultipartUpload(initiateMultipartUploadRequest);
            String uploadId = initiateMultipartUploadResult.getUploadId();

            // Copy parts.
            List<PartETag> partETags = new ArrayList<PartETag>();
            for (int i = 0; i < partCount; i++) {
                // Calculate the size of each part.
                long skipBytes = partSize * i;
                long size = partSize < contentLength - skipBytes ? partSize : contentLength - skipBytes;

                // Create an UploadPartCopyRequest object. You can specify conditions using UploadPartCopyRequest.
                UploadPartCopyRequest uploadPartCopyRequest =
                        new UploadPartCopyRequest(sourceBucketName, sourceKey, destinationBucketName, destinationKey);
                uploadPartCopyRequest.setUploadId(uploadId);
                uploadPartCopyRequest.setPartSize(size);
                uploadPartCopyRequest.setBeginIndex(skipBytes);
                uploadPartCopyRequest.setPartNumber(i + 1);
                UploadPartCopyResult uploadPartCopyResult = ossClient.uploadPartCopy(uploadPartCopyRequest);

                // Save the returned part ETags to partETags.
                partETags.add(uploadPartCopyResult.getPartETag());
            }

            // Complete the multipart copy task.
            CompleteMultipartUploadRequest completeMultipartUploadRequest = new CompleteMultipartUploadRequest(
                    destinationBucketName, destinationKey, uploadId, partETags);
            ossClient.completeMultipartUpload(completeMultipartUploadRequest);
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }
}     
# -*- coding: utf-8 -*-
import alibabacloud_oss_v2 as oss

# Obtain access credentials from environment variables. Before running this code example, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are set.
credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()

# Use the default configuration of the SDK.
cfg = oss.config.load_default()
cfg.credentials_provider = credentials_provider

# Specify the region in which the CloudBox is located, such as cn-hangzhou.
cfg.region = "cn-hangzhou"

# Specify the CloudBox ID. After you set the CloudBox ID, the SDK automatically switches the signing product to oss-cloudbox.
cfg.cloud_box_id = "cb-f8z7yvzgwfkl9q0h****"

# Specify the data domain in the CloudboxId.Region.oss-cloudbox.aliyuncs.com format.
cfg.endpoint = "cb-f8z7yvzgwfkl9q0h****.cn-hangzhou.oss-cloudbox.aliyuncs.com"

# Create an OSS client.
client = oss.Client(cfg)

# Specify the name of the source CloudBox bucket, such as srcexamplebucket.
source_bucket_name = "srcexamplebucket"
# Specify the full path of the source object. The full path cannot contain the bucket name.
source_key = "srcexampleobject.txt"
# Specify the name of the destination CloudBox bucket, which must be in the same region as the source bucket, such as desexamplebucket.
dest_bucket_name = "desexamplebucket"
# Specify the full path of the destination object. The full path cannot contain the bucket name.
dest_key = "desexampleobject.txt"

# Query the size of the object to copy.
result_meta = client.get_object_meta(oss.GetObjectMetaRequest(
    bucket=source_bucket_name,
    key=source_key,
))
total_size = result_meta.content_length

# Set the part size to 10 MB. Unit: bytes.
part_size = 10 * 1024 * 1024

# Initiate the copy task. The returned upload_id uniquely identifies the multipart upload task.
init_result = client.initiate_multipart_upload(oss.InitiateMultipartUploadRequest(
    bucket=dest_bucket_name,
    key=dest_key,
))
upload_id = init_result.upload_id

# Copy the parts.
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=dest_bucket_name,
        key=dest_key,
        upload_id=upload_id,
        part_number=part_number,
        source_bucket=source_bucket_name,
        source_key=source_key,
        source_range='bytes=' + str(offset) + '-' + str(end),
    ))
    # Save the ETag of the part to upload_parts.
    upload_parts.append(oss.UploadPart(part_number=part_number, etag=up_result.etag))
    offset += num_to_upload
    part_number += 1

# Sort the parts by part number in ascending order.
parts = sorted(upload_parts, key=lambda p: p.part_number)

# Complete the copy task.
result = client.complete_multipart_upload(oss.CompleteMultipartUploadRequest(
    bucket=dest_bucket_name,
    key=dest_key,
    upload_id=upload_id,
    complete_multipart_upload=oss.CompleteMultipartUpload(
        parts=parts
    ),
))
print(f'etag: {result.etag}')
package main

import (
	"context"
	"fmt"
	"log"

	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss"
	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials"
)

func main() {
	// Load the default configuration of the SDK and set the access credentials, region, CloudBox ID, and data domain.
	// Obtain access credentials from environment variables. Before running this code example, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are set.
	cfg := oss.LoadDefaultConfig().
		WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
		// Specify the region in which the CloudBox is located, such as cn-hangzhou.
		WithRegion("cn-hangzhou").
		// Specify the data domain in the CloudboxId.Region.oss-cloudbox.aliyuncs.com format.
		WithEndpoint("cb-f8z7yvzgwfkl9q0h****.cn-hangzhou.oss-cloudbox.aliyuncs.com").
		// Specify the CloudBox ID. After you set the CloudBox ID, the SDK automatically switches the signing product to oss-cloudbox.
		WithCloudBoxId("cb-f8z7yvzgwfkl9q0h****")

	// Create an OSS client.
	client := oss.NewClient(cfg)

	// Specify the name of the source CloudBox bucket, such as srcexamplebucket.
	sourceBucketName := "srcexamplebucket"
	// Specify the full path of the source object. The full path cannot contain the bucket name.
	sourceKey := "srcexampleobject.txt"
	// Specify the name of the destination CloudBox bucket, which must be in the same region as the source bucket, such as desexamplebucket.
	destBucketName := "desexamplebucket"
	// Specify the full path of the destination object. The full path cannot contain the bucket name.
	destKey := "desexampleobject.txt"

	// Query the size of the object to copy.
	headResult, err := client.HeadObject(context.TODO(), &oss.HeadObjectRequest{
		Bucket: oss.Ptr(sourceBucketName),
		Key:    oss.Ptr(sourceKey),
	})
	if err != nil {
		log.Fatalf("failed to head object %v", err)
	}
	total := headResult.ContentLength

	// Set the part size to 10 MB. Unit: bytes.
	partSize := int64(10 * 1024 * 1024)

	// Calculate the total number of parts.
	partCount := int((total + partSize - 1) / partSize)

	// Initiate the copy task. The returned UploadId uniquely identifies the multipart upload task.
	initResult, err := client.InitiateMultipartUpload(context.TODO(), &oss.InitiateMultipartUploadRequest{
		Bucket: oss.Ptr(destBucketName),
		Key:    oss.Ptr(destKey),
	})
	if err != nil {
		log.Fatalf("failed to initiate multipart upload %v", err)
	}
	uploadId := initResult.UploadId

	// Copy the parts.
	var parts []oss.UploadPart
	for i := 0; i < partCount; i++ {
		start := int64(i) * partSize
		end := start + partSize - 1
		if end > total-1 {
			end = total - 1
		}
		partRequest := &oss.UploadPartCopyRequest{
			Bucket:       oss.Ptr(destBucketName),
			Key:          oss.Ptr(destKey),
			SourceBucket: oss.Ptr(sourceBucketName),
			SourceKey:    oss.Ptr(sourceKey),
			PartNumber:   int32(i + 1),
			UploadId:     uploadId,
			Range:        oss.Ptr(fmt.Sprintf("bytes=%d-%d", start, end)),
		}
		partResult, err := client.UploadPartCopy(context.TODO(), partRequest)
		if err != nil {
			log.Fatalf("failed to upload part copy %v", err)
		}
		// Save the ETag of the part to parts.
		parts = append(parts, oss.UploadPart{
			PartNumber: partRequest.PartNumber,
			ETag:       partResult.ETag,
		})
	}

	// Complete the copy task.
	result, err := client.CompleteMultipartUpload(context.TODO(), &oss.CompleteMultipartUploadRequest{
		Bucket:   oss.Ptr(destBucketName),
		Key:      oss.Ptr(destKey),
		UploadId: uploadId,
		CompleteMultipartUpload: &oss.CompleteMultipartUpload{
			Parts: parts,
		},
	})
	if err != nil {
		log.Fatalf("failed to complete multipart upload %v", err)
	}
	log.Printf("etag: %v\n", oss.ToString(result.ETag))
}

Use ossutil

For more information about using ossutil to copy large objects, see cp (Copy files).

Use the REST API

If your program requires significant customization, you can make REST API requests directly. To make REST API requests, you must manually write code to calculate signatures. For more information, see UploadPartCopy.