This topic describes how to copy an object within a bucket or across buckets in the same region.
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.
You can call the CopyObject or UploadPartCopy operation to copy an object based on the object size. For more information about the object size limit, see CopyObject.
Upload a small object
To copy an object, you must have read permissions on the source object and read and write permissions on the destination bucket.
The source bucket and destination bucket must be in the same region. For example, objects cannot be copied from a bucket located in the China (Hangzhou) region to another bucket located in the China (Qingdao) region.
The following code provides an example on how to copy a small object by calling the CopyObject operation:
#include "oss_api.h"
#include "aos_http_io.h"
/* 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. */
const char *endpoint = "yourEndpoint";
/* Specify the name of the source bucket. */
const char *source_bucket_name = "yourSourceBucketName";
/* Specify the full path of the source object. Do not include the bucket name in the full path. */
const char *source_object_name = "yourSourceObjectName";
/* Specify the name of the destination bucket. The destination bucket must be in the same region as the source bucket. */
const char *dest_bucket_name = "yourDestBucketName";
/* Specify the full path of the destination object. Do not include the bucket name in the full path. */
const char *dest_object_name = "yourDestObjectName";
/* Specify the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the region to cn-hangzhou. */
const char *region = "yourRegion";
void init_options(oss_request_options_t *options)
{
options->config = oss_config_create(options->pool);
/* Use a char* string to initialize data of the aos_string_t type. */
aos_str_set(&options->config->endpoint, endpoint);
/* 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. */
aos_str_set(&options->config->access_key_id, getenv("OSS_ACCESS_KEY_ID"));
aos_str_set(&options->config->access_key_secret, getenv("OSS_ACCESS_KEY_SECRET"));
// Specify two additional parameters.
aos_str_set(&options->config->region, region);
options->config->signature_version = 4;
/* Specify whether to use CNAME. The value 0 indicates that CNAME is not used. */
options->config->is_cname = 0;
/* Specify network parameters, such as the timeout period. */
options->ctl = aos_http_controller_create(options->pool, 0);
}
int main(int argc, char *argv[])
{
/* Call the aos_http_io_initialize method in main() to initialize global resources, such as network resources and memory resources. */
if (aos_http_io_initialize(NULL, 0) != AOSE_OK) {
exit(1);
}
/* Create a memory pool to manage memory. aos_pool_t is equivalent to apr_pool_t. The code used to create a memory pool is included in the APR library. */
aos_pool_t *pool;
/* Create a memory pool. The value of the second parameter is NULL. This value indicates that the pool does not inherit other memory pools. */
aos_pool_create(&pool, NULL);
/* Create and initialize options. This parameter includes global configuration information, such as endpoint, access_key_id, access_key_secret, is_cname, and curl. */
oss_request_options_t *oss_client_options;
/* Allocate the memory resources in the memory pool to the options. */
oss_client_options = oss_request_options_create(pool);
/* Initialize oss_client_options. */
init_options(oss_client_options);
/* Initialize the parameters. */
aos_string_t source_bucket;
aos_string_t source_object;
aos_string_t dest_bucket;
aos_string_t dest_object;
aos_table_t *headers = NULL;
aos_table_t *resp_headers = NULL;
aos_status_t *resp_status = NULL;
aos_str_set(&source_bucket, source_bucket_name);
aos_str_set(&source_object, source_object_name);
aos_str_set(&dest_bucket, dest_bucket_name);
aos_str_set(&dest_object, dest_object_name);
headers = aos_table_make(pool, 0);
/* Copy the object. */
resp_status = oss_copy_object(oss_client_options, &source_bucket, &source_object, &dest_bucket, &dest_object, headers, &resp_headers);
if (aos_status_is_ok(resp_status)) {
printf("copy object succeeded\n");
} else {
printf("copy object failed\n");
}
/* Release the memory pool. This operation releases the memory resources allocated for the request. */
aos_pool_destroy(pool);
/* Release the allocated global resources. */
aos_http_io_deinitialize();
return 0;
}
Copy a large object
The following code provides an example on how to perform multipart copy by calling the UploadPartCopy operation:
#include "oss_api.h"
#include "aos_http_io.h"
#include <sys/stat.h>
/* 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. */
const char *endpoint = "yourEndpoint";
/* Specify the name of the source bucket. */
const char *source_bucket_name = "yourSourceBucketName";
/* Specify the full path of the source object. Do not include the bucket name in the full path. */
const char *source_object_name = "yourSourceObjectName";
/* Specify the name of the destination bucket. The destination bucket must be in the same region as the source bucket. */
const char *dest_bucket_name = "yourDestBucketName";
/* Specify the full path of the destination object. Do not include the bucket name in the full path. */
const char *dest_object_name = "yourDestObjectName";
/* Specify the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the region to cn-hangzhou. */
const char *region = "yourRegion";
void init_options(oss_request_options_t* options)
{
options->config = oss_config_create(options->pool);
/* Use a char* string to initialize data of the aos_string_t type. */
aos_str_set(&options->config->endpoint, endpoint);
/* 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. */
aos_str_set(&options->config->access_key_id, getenv("OSS_ACCESS_KEY_ID"));
aos_str_set(&options->config->access_key_secret, getenv("OSS_ACCESS_KEY_SECRET"));
// Specify two additional parameters.
aos_str_set(&options->config->region, region);
options->config->signature_version = 4;
/* Specify whether to use CNAME. The value 0 indicates that CNAME is not used. */
options->config->is_cname = 0;
/* Specify network parameters, such as the timeout period. */
options->ctl = aos_http_controller_create(options->pool, 0);
}
int main(int argc, char* argv[])
{
/* Call the aos_http_io_initialize method in main() to initialize global resources, such as network resources and memory resources. */
if (aos_http_io_initialize(NULL, 0) != AOSE_OK) {
exit(1);
}
/* Create a memory pool to manage memory. aos_pool_t is equivalent to apr_pool_t. The code used to create a memory pool is included in the APR library. */
aos_pool_t* pool;
/* Create a memory pool. The value of the second parameter is NULL. This value indicates that the pool does not inherit other memory pools. */
aos_pool_create(&pool, NULL);
/* Create and initialize options. This parameter includes global configuration information, such as endpoint, access_key_id, access_key_secret, is_cname, and curl. */
oss_request_options_t* oss_client_options;
/* Allocate the memory resources in the memory pool to the options. */
oss_client_options = oss_request_options_create(pool);
/* Initialize oss_client_options. */
init_options(oss_client_options);
/* Initialize the parameters. */
aos_string_t src_bucket;
aos_string_t src_object;
aos_string_t dest_bucket;
aos_string_t dest_object;
aos_string_t upload_id;
aos_table_t* headers = NULL;
aos_table_t* resp_headers = NULL;
aos_status_t* resp_status = NULL;
oss_list_upload_part_params_t* list_upload_part_params;
oss_upload_part_copy_params_t* upload_part_copy_params1;
oss_upload_part_copy_params_t* upload_part_copy_params2;
oss_list_part_content_t* part_content;
aos_list_t complete_part_list;
oss_complete_part_content_t* complete_content;
aos_table_t* list_part_resp_headers = NULL;
aos_table_t* complete_resp_headers = NULL;
int part1 = 1;
int part2 = 2;
int64_t range_start1 = 0;
int64_t range_end1 = 6000000;//not less than 5MB
int64_t range_start2 = 6000001;
int64_t range_end2;
int max_ret = 1000;
int64_t content_length = 0;
/* Obtain the size of the source object. */
headers = aos_table_make(pool, 0);
aos_str_set(&src_bucket, source_bucket_name);
aos_str_set(&src_object, source_object_name);
resp_status = oss_head_object(oss_client_options, &src_bucket, &src_object, headers, &resp_headers);
if (aos_status_is_ok(resp_status)) {
char *content_length_str = (char*)apr_table_get(resp_headers, OSS_CONTENT_LENGTH);
if (content_length_str != NULL) {
content_length = atoll(content_length_str);
}
printf("head object succeeded\n");
}
else {
printf("head object failed\n");
}
/* Initiate a multipart copy task. */
headers = aos_table_make(pool, 0);
aos_str_set(&dest_bucket, dest_bucket_name);
aos_str_set(&dest_object, dest_object_name);
resp_status = oss_init_multipart_upload(oss_client_options, &dest_bucket, &dest_object, &upload_id, headers, &resp_headers);
if (aos_status_is_ok(resp_status)) {
printf("init multipart upload succeeded, upload_id is %s\n", upload_id.data);
}
else {
printf("init multipart upload failed\n");
}
/* Copy the first part. */
upload_part_copy_params1 = oss_create_upload_part_copy_params(pool);
aos_str_set(&upload_part_copy_params1->source_bucket, source_bucket_name);
aos_str_set(&upload_part_copy_params1->source_object, source_object_name);
aos_str_set(&upload_part_copy_params1->dest_bucket, dest_bucket_name);
aos_str_set(&upload_part_copy_params1->dest_object, dest_object_name);
aos_str_set(&upload_part_copy_params1->upload_id, upload_id.data);
upload_part_copy_params1->part_num = part1;
upload_part_copy_params1->range_start = range_start1;
upload_part_copy_params1->range_end = range_end1;
headers = aos_table_make(pool, 0);
resp_status = oss_upload_part_copy(oss_client_options, upload_part_copy_params1, headers, &resp_headers);
if (aos_status_is_ok(resp_status)) {
printf("upload part 1 copy succeeded\n");
}
else {
printf("upload part 1 copy failed\n");
}
/* Copy the second part. */
range_end2 = content_length - 1;
upload_part_copy_params2 = oss_create_upload_part_copy_params(pool);
aos_str_set(&upload_part_copy_params2->source_bucket, source_bucket_name);
aos_str_set(&upload_part_copy_params2->source_object, source_object_name);
aos_str_set(&upload_part_copy_params2->dest_bucket, dest_bucket_name);
aos_str_set(&upload_part_copy_params2->dest_object, dest_object_name);
aos_str_set(&upload_part_copy_params2->upload_id, upload_id.data);
upload_part_copy_params2->part_num = part2;
upload_part_copy_params2->range_start = range_start2;
upload_part_copy_params2->range_end = range_end2;
headers = aos_table_make(pool, 0);
resp_status = oss_upload_part_copy(oss_client_options, upload_part_copy_params2, headers, &resp_headers);
if (aos_status_is_ok(resp_status)) {
printf("upload part 2 copy succeeded\n");
}
else {
printf("upload part 2 copy failed\n");
}
/* List the copied parts. */
headers = aos_table_make(pool, 0);
list_upload_part_params = oss_create_list_upload_part_params(pool);
list_upload_part_params->max_ret = max_ret;
aos_list_init(&complete_part_list);
resp_status = oss_list_upload_part(oss_client_options, &dest_bucket, &dest_object, &upload_id, list_upload_part_params, &list_part_resp_headers);
aos_list_for_each_entry(oss_list_part_content_t, part_content, &list_upload_part_params->part_list, node) {
complete_content = oss_create_complete_part_content(pool);
aos_str_set(&complete_content->part_number, part_content->part_number.data);
aos_str_set(&complete_content->etag, part_content->etag.data);
aos_list_add_tail(&complete_content->node, &complete_part_list);
}
/* Complete the multipart copy task. */
resp_status = oss_complete_multipart_upload(oss_client_options, &dest_bucket, &dest_object, &upload_id, &complete_part_list, headers, &complete_resp_headers);
if (aos_status_is_ok(resp_status)) {
printf("complete multipart upload succeeded\n");
}
else {
printf("complete multipart upload failed\n");
}
/* Release the memory pool. This operation releases the memory resources allocated for the request. */
aos_pool_destroy(pool);
/* Release the allocated global resources. */
aos_http_io_deinitialize();
return 0;
}
References
Copy a small object
For more information about the API operation that you can call to copy a small object, see CopyObject.
Copy a large object
For more information about the API operation that you can call to copy a large object, see UploadPartCopy.