简介
本文介绍对象存储 COS 通过 C SDK 实现上传对象功能的示例代码和描述。包括高级接口、简单接口、分块上传三个部分。
注意事项
若您使用简单上传,需要具有目标对象的写权限:在您进行 授权策略 时,action 需要设置为
cos:PutObject
,更多授权请参见 支持CAM的业务接口。若您使用高级接口的自动分块上传或使用简单接口实现分块上传,需要具有目标对象的初始化分块上传、上传分块、完成分块上传的权限:在您进行 授权策略 时,action 需要设置为
cos:InitiateMultipartUpload
,cos:UploadPart
,cos:CompleteMultipartUpload
,更多授权请参见 支持CAM的业务接口。若您使用高级接口的断点续传,需要具有目标对象的初始化分块上传、上传分块、完成分块上传、列举分块上传任务、列举已上传分块的权限:在您进行 授权策略 时,action 需要设置为
cos:InitiateMultipartUpload
,cos:UploadPart
,cos:CompleteMultipartUpload
,cos:ListMultipartUploads
,cos:ListParts
更多授权请参见 支持CAM的业务接口。相关示例
功能名称 | 描述 | 示例代码 |
高级接口 | 高级接口封装了简单上传、分块上传接口,支持断点续传功能。 | |
简单接口 | PUT Object 接口可以上传一个对象至指定存储桶中,不支持自动分块上传和断点续传。最大支持上传不超过5GB的对象,5GB以上对象请使用 分块上传 或 高级接口 上传。 | |
分块操作 | 分块上传可以实现将整个对象切分为多个分块,然后再将这些分块上传到对象存储(Cloud Object Storage,COS)。 |
高级接口(推荐)
上传本地文件
说明:
该 Demo 示范如何使用高级上传接口进行对象上传。
仅支持文件上传,不支持流式上传,内部封装了分块上传的各接口。
分块大小默认 1048576(1MB),可通过 part_size 参数调整。
方法原型
cos_status_t *cos_resumable_upload_file(cos_request_options_t *options,cos_string_t *bucket,cos_string_t *object,cos_string_t *filepath,cos_table_t *headers,cos_table_t *params,cos_resumable_clt_params_t *clt_params,cos_progress_callback progress_callback,cos_table_t **resp_headers,cos_list_t *resp_body)
请求示例
// COS 的 bucket 名称, [bucket]-[appid], 如: mybucket-1253666666,可在 https://console.cloud.tencent.com/cos5/bucket 查看char bucket_name[] = "examplebucket-12500000000";// 开发者访问 COS 服务时拥有的用户维度唯一资源标识,用以标识资源,可在 https://console.cloud.tencent.com/cam/capi 页面获取char appid[] = "12500000000";// 开发者拥有的项目身份ID/密钥,可在 https://console.cloud.tencent.com/cam/capi 页面获取char secret_id[] = "AKIDXXXXXXXX";char secret_key[] = "1A2Z3YYYYYYYYYY";//endpoint 是 COS 访问域名信息(不设置存储桶前缀,访问 COS 时会自动在前面拼接上[bucket]-[appid]), 详情请参见 https://cloud.tencent.com/document/product/436/6224 文档char endpoint[] = "cos.ap-guangzhou.myqcloud.com";// 是否使用自定域名。如果设置为 COS_TRUE ,则访问 COS 时需要将 endpoint 的值修改为自定义域名int is_cname = COS_FALSE;void init_test_config(cos_config_t* config, int is_cname) {cos_str_set(&config->endpoint, endpoint);cos_str_set(&config->access_key_id, secret_id);cos_str_set(&config->access_key_secret, secret_key);cos_str_set(&config->appid, appid);// cos_str_set(&config->sts_token, token); // 使用临时密钥时的 tokenconfig->is_cname = is_cname; // 是否使用自定义域名}void init_test_request_options(cos_request_options_t* options, int is_cname) {options->config = cos_config_create(options->pool);init_test_config(options->config, is_cname);options->ctl = cos_http_controller_create(options->pool, 0);}void log_status(cos_status_t* s) {cos_warn_log("status->code: %d", s->code);if (s->error_code)cos_warn_log("status->error_code: %s", s->error_code);if (s->error_msg)cos_warn_log("status->error_msg: %s", s->error_msg);if (s->req_id)cos_warn_log("status->req_id: %s", s->req_id);}void resumable_put_object_demo() {char object_name[] = "big_file2.txt"; // 对象名称char file_path[] = "big_file.txt"; // 本地文件路径int enable_checkpoint = COS_FALSE; // 是否开启断点续传cos_pool_t* p = NULL;cos_string_t bucket;cos_string_t object;cos_string_t filename;cos_status_t* s = NULL;cos_table_t* headers = NULL;cos_table_t* resp_headers = NULL;cos_request_options_t* options = NULL;cos_resumable_clt_params_t* clt_params;cos_pool_create(&p, NULL);options = cos_request_options_create(p);init_test_request_options(options, is_cname);headers = cos_table_make(p, 0);cos_str_set(&bucket, bucket_name);cos_str_set(&object, object_name);cos_str_set(&filename, file_path);// uploadclt_params = cos_create_resumable_clt_params_content(p, 1024 * 1024 * 5, 8, enable_checkpoint, NULL);s = cos_resumable_upload_file(options, &bucket, &object, &filename, headers, NULL,clt_params, NULL, &resp_headers, NULL);log_status(s);if (cos_status_is_ok(s)) {printf("upload succeeded\\n");} else {printf("upload failed\\n");}cos_pool_destroy(p);}int main() {if (cos_http_io_initialize(NULL, 0) != COSE_OK) {exit(1);}resumable_put_object_demo();// cos_http_io_deinitialize lastcos_http_io_deinitialize();return 0;}
参数说明
参数名称 | 参数描述 | 类型 |
options | COS 请求选项 | Struct |
bucket | 存储桶名称,存储桶的命名格式为 BucketName-APPID,此处填写的存储桶名称必须为此格式 | String |
object | Object 名称 | String |
filepath | Object 本地文件名称 | String |
headers | COS 请求附加头域 | Struct |
params | COS 请求操作参数 | Struct |
clt_params | 上传对象控制参数 | Struct |
clt_params.part_size | 块大小,单位为 bytes,如果用户指定的 part_size 小于1048576(1MB), 由 C SDK 自动切分, 分块大小默认1048576(1MB),如果分块数超过10000,则根据文件大小调整 | Int |
clt_params.thread_num | 线程池大小,默认为1 | Int |
clt_params.enable_checkpoint | 是否使能断点续传 | bool |
clt_params.checkpoint_path | 当使能断点续传时,表示保存上传进度的文件路径,默认路径为 <filepath>.cp ,其中 filepath 为 Object 本地文件名称 | String |
progress_callback | 上传进度回调函数 | Struct |
resp_headers | 返回 HTTP 响应消息的头域 | Struct |
resp_body | 保存完成分块上传请求时返回的数据 | Struct |
返回结果说明
CosResult 主要成员函数说明如下:
返回结果 | 描述 | 类型 |
code | 错误码 | Int |
error_code | 错误码内容 | String |
error_msg | 错误码描述 | String |
req_id | 请求消息 ID | String |
简单操作
上传本地文件
方法原型
cos_status_t *cos_put_object_from_file(const cos_request_options_t *options,const cos_string_t *bucket,const cos_string_t *object,const cos_string_t *filename,cos_table_t *headers,cos_table_t **resp_headers)
请求示例
// COS 的 bucket 名称, [bucket]-[appid], 如: mybucket-1253666666,可在 https://console.cloud.tencent.com/cos5/bucket 查看char bucket_name[] = "examplebucket-12500000000";// 开发者访问 COS 服务时拥有的用户维度唯一资源标识,用以标识资源,可在 https://console.cloud.tencent.com/cam/capi 页面获取char appid[] = "12500000000";// 开发者拥有的项目身份ID/密钥,可在 https://console.cloud.tencent.com/cam/capi 页面获取char secret_id[] = "AKIDXXXXXXXX";char secret_key[] = "1A2Z3YYYYYYYYYY";//endpoint 是 COS 访问域名信息(不设置存储桶前缀,访问 COS 时会自动在前面拼接上[bucket]-[appid]), 详情请参见 https://cloud.tencent.com/document/product/436/6224 文档char endpoint[] = "cos.ap-guangzhou.myqcloud.com";// 是否使用自定域名。如果设置为 COS_TRUE ,则访问 COS 时需要将 endpoint 的值修改为自定义域名int is_cname = COS_FALSE;void init_test_config(cos_config_t* config, int is_cname) {cos_str_set(&config->endpoint, endpoint);cos_str_set(&config->access_key_id, secret_id);cos_str_set(&config->access_key_secret, secret_key);cos_str_set(&config->appid, appid);// cos_str_set(&config->sts_token, token); // 使用临时密钥时的 tokenconfig->is_cname = is_cname; // 是否使用自定义域名}void init_test_request_options(cos_request_options_t* options, int is_cname) {options->config = cos_config_create(options->pool);init_test_config(options->config, is_cname);options->ctl = cos_http_controller_create(options->pool, 0);}void log_status(cos_status_t* s) {cos_warn_log("status->code: %d", s->code);if (s->error_code)cos_warn_log("status->error_code: %s", s->error_code);if (s->error_msg)cos_warn_log("status->error_msg: %s", s->error_msg);if (s->req_id)cos_warn_log("status->req_id: %s", s->req_id);}void put_object_from_file_demo() {char object_name[] = "test.txt"; // 对象名称char file_path[] = "test.txt"; // 本地文件路径cos_pool_t* p = NULL;cos_status_t* s = NULL;cos_request_options_t* options = NULL;cos_string_t bucket;cos_string_t object;cos_string_t file;cos_table_t* resp_headers = NULL;cos_table_t* headers = NULL;// 创建内存池cos_pool_create(&p, NULL);// 初始化请求选项options = cos_request_options_create(p);init_test_request_options(options, is_cname);cos_str_set(&bucket, bucket_name);// 限速值设置范围为819200 - 838860800,即100KB/s - 100MB/s,如果超出该范围将返回400错误// headers = cos_table_make(p, 1);// cos_table_add_int(headers, "x-cos-traffic-limit", 819200);// 上传对象cos_str_set(&file, file_path);cos_str_set(&object, object_name);s = cos_put_object_from_file(options, &bucket, &object, &file, headers, &resp_headers);if (cos_status_is_ok(s)) {printf("put object succeeded\\n");} else {printf("put object failed\\n");}log_status(s);// 销毁内存池cos_pool_destroy(p);}int main() {if (cos_http_io_initialize(NULL, 0) != COSE_OK) {exit(1);}put_object_from_file_demo();// cos_http_io_deinitialize lastcos_http_io_deinitialize();return 0;}
参数说明
参数名称 | 参数描述 | 类型 |
options | COS 请求选项 | Struct |
bucket | 存储桶名称,存储桶的命名格式为 BucketName-APPID,此处填写的存储桶名称必须为此格式 | String |
object | Object 名称 | String |
filename | Object 本地保存文件名称 | String |
headers | COS 请求附加头域 | Struct |
resp_headers | 返回 HTTP 响应消息的头域 | Struct |
返回结果说明
返回结果 | 描述 | 类型 |
code | 错误码 | Int |
error_code | 错误码内容 | String |
error_msg | 错误码描述 | String |
req_id | 请求消息 ID | String |
上传 buffer 数据
方法原型
cos_status_t *cos_put_object_from_buffer(const cos_request_options_t *options,const cos_string_t *bucket,const cos_string_t *object,cos_list_t *buffer,cos_table_t *headers,cos_table_t **resp_headers)
请求示例
// COS 的 bucket 名称, [bucket]-[appid], 如: mybucket-1253666666,可在 https://console.cloud.tencent.com/cos5/bucket 查看char bucket_name[] = "examplebucket-12500000000";// 开发者访问 COS 服务时拥有的用户维度唯一资源标识,用以标识资源,可在 https://console.cloud.tencent.com/cam/capi 页面获取char appid[] = "12500000000";// 开发者拥有的项目身份ID/密钥,可在 https://console.cloud.tencent.com/cam/capi 页面获取char secret_id[] = "AKIDXXXXXXXX";char secret_key[] = "1A2Z3YYYYYYYYYY";//endpoint 是 COS 访问域名信息(不设置存储桶前缀,访问 COS 时会自动在前面拼接上[bucket]-[appid]), 详情请参见 https://cloud.tencent.com/document/product/436/6224 文档char endpoint[] = "cos.ap-guangzhou.myqcloud.com";// 是否使用自定域名。如果设置为 COS_TRUE ,则访问 COS 时需要将 endpoint 的值修改为自定义域名int is_cname = COS_FALSE;void init_test_config(cos_config_t* config, int is_cname) {cos_str_set(&config->endpoint, endpoint);cos_str_set(&config->access_key_id, secret_id);cos_str_set(&config->access_key_secret, secret_key);cos_str_set(&config->appid, appid);// cos_str_set(&config->sts_token, token); // 使用临时密钥时的 tokenconfig->is_cname = is_cname; // 是否使用自定义域名}void init_test_request_options(cos_request_options_t* options, int is_cname) {options->config = cos_config_create(options->pool);init_test_config(options->config, is_cname);options->ctl = cos_http_controller_create(options->pool, 0);}void log_status(cos_status_t* s) {cos_warn_log("status->code: %d", s->code);if (s->error_code)cos_warn_log("status->error_code: %s", s->error_code);if (s->error_msg)cos_warn_log("status->error_msg: %s", s->error_msg);if (s->req_id)cos_warn_log("status->req_id: %s", s->req_id);}void put_object_from_buffer_demo() {char object_name[] = "test.txt"; // 对象名称cos_pool_t* p = NULL;cos_status_t* s = NULL;cos_request_options_t* options = NULL;cos_string_t bucket;cos_string_t object;cos_table_t* resp_headers;cos_table_t* headers = NULL;cos_pool_create(&p, NULL);options = cos_request_options_create(p);init_test_request_options(options, is_cname);cos_str_set(&bucket, bucket_name);cos_str_set(&object, object_name);// buffer 数据cos_list_t buffer;cos_buf_t* content = NULL;char* str = "This is my test data.";cos_list_init(&buffer);content = cos_buf_pack(options->pool, str, strlen(str));cos_list_add_tail(&content->node, &buffer);s = cos_put_object_from_buffer(options, &bucket, &object,&buffer, headers, &resp_headers);if (cos_status_is_ok(s)) {printf("put object succeeded\\n");} else {printf("put object failed\\n");}log_status(s);cos_pool_destroy(p);}int main() {if (cos_http_io_initialize(NULL, 0) != COSE_OK) {exit(1);}put_object_from_buffer_demo();// cos_http_io_deinitialize lastcos_http_io_deinitialize();return 0;}
参数说明
参数名称 | 参数描述 | 类型 |
options | COS 请求选项 | Struct |
bucket | 存储桶名称,存储桶的命名格式为 BucketName-APPID,此处填写的存储桶名称必须为此格式 | String |
object | Object 名称 | String |
buffer | Object 内容 | cos_list_t |
headers | COS 请求附加头域 | Struct |
resp_headers | 返回 HTTP 响应消息的头域 | Struct |
返回结果说明
返回结果 | 描述 | 类型 |
code | 错误码 | Int |
error_code | 错误码内容 | String |
error_msg | 错误码描述 | String |
req_id | 请求消息 ID | String |
创建文件夹
说明:
COS 上可以将以
/
分隔的对象路径看做一个虚拟文件夹,根据此特性,可以上传一个空的流,并且命名以 /
结尾,可实现在 COS 上创建一个空文件夹。方法原型
cos_status_t *cos_put_object_from_buffer(const cos_request_options_t *options,const cos_string_t *bucket,const cos_string_t *object,cos_list_t *buffer,cos_table_t *headers,cos_table_t **resp_headers)
请求示例
// COS 的 bucket 名称, [bucket]-[appid], 如: mybucket-1253666666,可在 https://console.cloud.tencent.com/cos5/bucket 查看char bucket_name[] = "examplebucket-12500000000";// 开发者访问 COS 服务时拥有的用户维度唯一资源标识,用以标识资源,可在 https://console.cloud.tencent.com/cam/capi 页面获取char appid[] = "12500000000";// 开发者拥有的项目身份ID/密钥,可在 https://console.cloud.tencent.com/cam/capi 页面获取char secret_id[] = "AKIDXXXXXXXX";char secret_key[] = "1A2Z3YYYYYYYYYY";//endpoint 是 COS 访问域名信息(不设置存储桶前缀,访问 COS 时会自动在前面拼接上[bucket]-[appid]), 详情请参见 https://cloud.tencent.com/document/product/436/6224 文档char endpoint[] = "cos.ap-guangzhou.myqcloud.com";// 是否使用自定域名。如果设置为 COS_TRUE ,则访问 COS 时需要将 endpoint 的值修改为自定义域名int is_cname = COS_FALSE;void init_test_config(cos_config_t* config, int is_cname) {cos_str_set(&config->endpoint, endpoint);cos_str_set(&config->access_key_id, secret_id);cos_str_set(&config->access_key_secret, secret_key);cos_str_set(&config->appid, appid);// cos_str_set(&config->sts_token, token); // 使用临时密钥时的 tokenconfig->is_cname = is_cname; // 是否使用自定义域名}void init_test_request_options(cos_request_options_t* options, int is_cname) {options->config = cos_config_create(options->pool);init_test_config(options->config, is_cname);options->ctl = cos_http_controller_create(options->pool, 0);}void log_status(cos_status_t* s) {cos_warn_log("status->code: %d", s->code);if (s->error_code)cos_warn_log("status->error_code: %s", s->error_code);if (s->error_msg)cos_warn_log("status->error_msg: %s", s->error_msg);if (s->req_id)cos_warn_log("status->req_id: %s", s->req_id);}void put_object_dir_demo() {// COS 上可以将以 / 分隔的对象路径看做一个虚拟文件夹,根据此特性,可以上传一个空的流,并且命名以 / 结尾,可实现在 COS 上创建一个空文件夹。char dir_name[] = "test/"; // 目录名称,末尾需要加/cos_pool_t* p = NULL;cos_status_t* s = NULL;cos_request_options_t* options = NULL;cos_string_t bucket;cos_string_t object;cos_table_t* resp_headers;cos_table_t* headers = NULL;cos_list_t buffer;cos_pool_create(&p, NULL);options = cos_request_options_create(p);init_test_request_options(options, is_cname);cos_str_set(&bucket, bucket_name);cos_str_set(&object, dir_name);// 上传文件夹cos_list_init(&buffer);s = cos_put_object_from_buffer(options, &bucket, &object,&buffer, headers, &resp_headers);if (cos_status_is_ok(s)) {printf("put dir succeeded\\n");} else {printf("put dir failed\\n");}log_status(s);cos_pool_destroy(p);}int main() {if (cos_http_io_initialize(NULL, 0) != COSE_OK) {exit(1);}put_object_dir_demo();// cos_http_io_deinitialize lastcos_http_io_deinitialize();return 0;}
参数说明
参数名称 | 参数描述 | 类型 |
options | COS 请求选项 | Struct |
bucket | 存储桶名称,存储桶的命名格式为 BucketName-APPID,此处填写的存储桶名称必须为此格式 | String |
object | Object 名称 | String |
buffer | Object 内容 | cos_list_t |
headers | COS 请求附加头域 | Struct |
resp_headers | 返回 HTTP 响应消息的头域 | Struct |
返回结果说明
返回结果 | 描述 | 类型 |
code | 错误码 | Int |
error_code | 错误码内容 | String |
error_msg | 错误码描述 | String |
req_id | 请求消息 ID | String |
分块操作
说明:
如果要上传的文件可以完整获取,推荐使用高级接口。
操作流程
分块上传的流程
1. 初始化分块上传(Initiate Multipart Upload),得到 UploadId。
2. 使用 UploadId 上传分块(Upload Part)。
3. 完成分块上传(Complete Multipart Upload)。
分块继续上传的流程
1. 如果没有记录 UploadId,则要先查询分块上传任务(List Multipart Uploads),得到对应文件的 UploadId。
2. 使用 UploadId 列出已上传的分块(List Parts)。
3. 使用 UploadId 上传剩余的分块(Upload Part)。
4. 完成分块上传(Complete Multipart Upload)。
终止分块上传的流程
1. 如果没有记录 UploadId,则查询分块上传任务(List Multipart Uploads),得到对应文件的 UploadId。
2. 终止分块上传并删除已上传分块(Abort Multipart Upload)。
使用案例:初始化分块上传
初始化分块上传操作,获取对应的 uploadId 用于后续的操作。
方法原型
cos_status_t *cos_init_multipart_upload(const cos_request_options_t *options,const cos_string_t *bucket,const cos_string_t *object,cos_string_t *upload_id,cos_table_t *headers,cos_table_t **resp_headers)
请求示例
// COS 的 bucket 名称, [bucket]-[appid], 如: mybucket-1253666666,可在 https://console.cloud.tencent.com/cos5/bucket 查看char bucket_name[] = "examplebucket-12500000000";// 开发者访问 COS 服务时拥有的用户维度唯一资源标识,用以标识资源,可在 https://console.cloud.tencent.com/cam/capi 页面获取char appid[] = "12500000000";// 开发者拥有的项目身份ID/密钥,可在 https://console.cloud.tencent.com/cam/capi 页面获取char secret_id[] = "AKIDXXXXXXXX";char secret_key[] = "1A2Z3YYYYYYYYYY";//endpoint 是 COS 访问域名信息(不设置存储桶前缀,访问 COS 时会自动在前面拼接上[bucket]-[appid]), 详情请参见 https://cloud.tencent.com/document/product/436/6224 文档char endpoint[] = "cos.ap-guangzhou.myqcloud.com";// 是否使用自定域名。如果设置为 COS_TRUE ,则访问 COS 时需要将 endpoint 的值修改为自定义域名int is_cname = COS_FALSE;void init_test_config(cos_config_t* config, int is_cname) {cos_str_set(&config->endpoint, endpoint);cos_str_set(&config->access_key_id, secret_id);cos_str_set(&config->access_key_secret, secret_key);cos_str_set(&config->appid, appid);// cos_str_set(&config->sts_token, token); // 使用临时密钥时的 tokenconfig->is_cname = is_cname; // 是否使用自定义域名}void init_test_request_options(cos_request_options_t* options, int is_cname) {options->config = cos_config_create(options->pool);init_test_config(options->config, is_cname);options->ctl = cos_http_controller_create(options->pool, 0);}void log_status(cos_status_t* s) {cos_warn_log("status->code: %d", s->code);if (s->error_code)cos_warn_log("status->error_code: %s", s->error_code);if (s->error_msg)cos_warn_log("status->error_msg: %s", s->error_msg);if (s->req_id)cos_warn_log("status->req_id: %s", s->req_id);}void init_multipart_upload_demo(){char object_name[] = "test.txt"; // 对象名称cos_pool_t *p = NULL;cos_status_t *s = NULL;cos_request_options_t *options = NULL;cos_string_t bucket;cos_string_t object;cos_string_t upload_id;cos_table_t *resp_headers = NULL;//创建内存池cos_pool_create(&p, NULL);//初始化请求选项options = cos_request_options_create(p);init_test_request_options(options, is_cname);cos_str_set(&bucket, bucket_name);//初始化分块上传cos_str_set(&object, object_name);s = cos_init_multipart_upload(options, &bucket, &object,&upload_id, NULL, &resp_headers);if (cos_status_is_ok(s)) {printf("init multipart upload succeeded\\n");} else {printf("init multipart upload failed\\n");}//销毁内存池cos_pool_destroy(p);}int main(int argc, char *argv[]){if (cos_http_io_initialize(NULL, 0) != COSE_OK) {exit(1);}init_multipart_upload_demo();cos_http_io_deinitialize();return 0;}
参数说明
参数名称 | 参数描述 | 类型 |
options | COS 请求选项 | Struct |
bucket | 存储桶名称,存储桶的命名格式为 BucketName-APPID,此处填写的存储桶名称必须为此格式 | String |
object | Object 名称 | String |
upload_id | 操作返回的 Upload ID | String |
headers | COS 请求附加头域 | Struct |
resp_headers | 返回 HTTP 响应消息的头域 | Struct |
返回结果说明
返回结果 | 描述 | 类型 |
code | 错误码 | Int |
error_code | 错误码内容 | String |
error_msg | 错误码描述 | String |
req_id | 请求消息 ID | String |
使用案例:查询分块上传任务
查询分块上传任务(List Multipart Uploads),获取当前正在进行的所有上传任务,可以从中找到需要处理的 uploadId。
方法原型
cos_status_t *cos_list_multipart_upload(const cos_request_options_t *options,const cos_string_t *bucket,cos_list_multipart_upload_params_t *params,cos_table_t **resp_headers);
请求示例
// COS 的 bucket 名称, [bucket]-[appid], 如: mybucket-1253666666,可在 https://console.cloud.tencent.com/cos5/bucket 查看char bucket_name[] = "examplebucket-12500000000";// 开发者访问 COS 服务时拥有的用户维度唯一资源标识,用以标识资源,可在 https://console.cloud.tencent.com/cam/capi 页面获取char appid[] = "12500000000";// 开发者拥有的项目身份ID/密钥,可在 https://console.cloud.tencent.com/cam/capi 页面获取char secret_id[] = "AKIDXXXXXXXX";char secret_key[] = "1A2Z3YYYYYYYYYY";//endpoint 是 COS 访问域名信息(不设置存储桶前缀,访问 COS 时会自动在前面拼接上[bucket]-[appid]), 详情请参见 https://cloud.tencent.com/document/product/436/6224 文档char endpoint[] = "cos.ap-guangzhou.myqcloud.com";// 是否使用自定域名。如果设置为 COS_TRUE ,则访问 COS 时需要将 endpoint 的值修改为自定义域名int is_cname = COS_FALSE;void init_test_config(cos_config_t* config, int is_cname) {cos_str_set(&config->endpoint, endpoint);cos_str_set(&config->access_key_id, secret_id);cos_str_set(&config->access_key_secret, secret_key);cos_str_set(&config->appid, appid);// cos_str_set(&config->sts_token, token); // 使用临时密钥时的 tokenconfig->is_cname = is_cname; // 是否使用自定义域名}void init_test_request_options(cos_request_options_t* options, int is_cname) {options->config = cos_config_create(options->pool);init_test_config(options->config, is_cname);options->ctl = cos_http_controller_create(options->pool, 0);}void log_status(cos_status_t* s) {cos_warn_log("status->code: %d", s->code);if (s->error_code)cos_warn_log("status->error_code: %s", s->error_code);if (s->error_msg)cos_warn_log("status->error_msg: %s", s->error_msg);if (s->req_id)cos_warn_log("status->req_id: %s", s->req_id);}void list_multipart_demo(){cos_pool_t *p = NULL;cos_string_t bucket;cos_table_t *resp_headers = NULL;cos_request_options_t *options = NULL;cos_status_t *s = NULL;cos_list_multipart_upload_params_t *list_multipart_params = NULL;cos_pool_create(&p, NULL);options = cos_request_options_create(p);init_test_request_options(options, is_cname);cos_str_set(&bucket, bucket_name);list_multipart_params = cos_create_list_multipart_upload_params(p);list_multipart_params->max_ret = 999;s = cos_list_multipart_upload(options, &bucket, list_multipart_params, &resp_headers);log_status(s);if (cos_status_is_ok(s)) {printf("List multipart succeeded\\n");cos_list_multipart_upload_content_t *content = NULL;cos_list_for_each_entry(cos_list_multipart_upload_content_t, content, &list_multipart_params->upload_list, node) {printf("initiated = %s, upload_id = %s, key = %s\\n",content->initiated.data,content->upload_id.data,content->key.data);}} else {printf("List multipart failed\\n");}cos_pool_destroy(p);}int main() {if (cos_http_io_initialize(NULL, 0) != COSE_OK) {exit(1);}list_multipart_demo();// cos_http_io_deinitialize lastcos_http_io_deinitialize();return 0;}
参数说明
参数名称 | 参数描述 | 类型 |
options | COS 请求选项 | Struct |
bucket | 存储桶名称,存储桶的命名格式为 BucketName-APPID,此处填写的存储桶名称必须为此格式 | String |
params | List Multipart Uploads 操作参数 | Struct |
params.encoding_type | 规定返回值的编码方式 | String |
params.prefix | 前缀匹配,用来规定返回的文件前缀地址 | String |
params.delimiter | 界符为一个符号: 如果有 Prefix,则将 Prefix 到 delimiter 之间的相同路径归为一类,定义为 Common Prefix,然后列出所有 Common Prefix 如果没有 Prefix,则从路径起点开始 | String |
params.max_ret | 单次返回最大的条目数量,默认1000 | String |
params.key_marker | 与 upload-id-marker 一起使用: 当 upload-id-marker 未被指定时,ObjectName 字母顺序大于 key-marker 的条目将被列出 当 upload-id-marker 被指定时,ObjectName 字母顺序大于 key-marker 的条目被列出,ObjectName 字母顺序等于 key-marker 同时 UploadID 大于 upload-id-marker 的条目将被列出 | String |
params.upload_id_marker | 与 key-marker 一起使用: 当 key-marker 未被指定时,upload-id-marker 将被忽略 当 key-marker 被指定时,ObjectName 字母顺序大于 key-marker 的条目被列出,ObjectName 字母顺序等于 key-marker 同时 UploadID 大于 upload-id-marker 的条目将被列出 | String |
params.truncated | 返回条目是否被截断,'true' 或者 'false' | Boolean |
params.next_key_marker | 假如返回条目被截断,则返回 NextKeyMarker 就是下一个条目的起点 | String |
params.next_upload_id_marker | 假如返回条目被截断,则返回 UploadId 就是下一个条目的起点 | String |
params.upload_list | 分块上传的信息 | Struct |
params.upload_list.key | Object 的名称 | String |
params.upload_list.upload_id | 表示本次分块上传的 ID | String |
params.upload_list.initiated | 表示本次分块上传任务的启动时间 | String |
resp_headers | 返回 HTTP 响应消息的头域 | Struct |
typedef struct {cos_list_t node;cos_string_t key;cos_string_t upload_id;cos_string_t initiated;} cos_list_multipart_upload_content_t;
返回结果说明
返回结果 | 描述 | 类型 |
code | 错误码 | Int |
error_code | 错误码内容 | String |
error_msg | 错误码描述 | String |
req_id | 请求消息 ID | String |
使用案例:上传分块
说明:
分块上传文件。Upload Part 请求实现在初始化以后的分块上传,支持的块的数量为1 - 10000,块的大小为1MB - 5GB。在每次请求 Upload Part 时,需要携带 partNumber 和 uploadID,partNumber 为块的编号,支持乱序上传。
方法原型
cos_status_t *cos_upload_part_from_file(const cos_request_options_t *options,const cos_string_t *bucket,const cos_string_t *object,const cos_string_t *upload_id,int part_num,cos_upload_file_t *upload_file,cos_table_t **resp_headers);
请求示例
// COS 的 bucket 名称, [bucket]-[appid], 如: mybucket-1253666666,可在 https://console.cloud.tencent.com/cos5/bucket 查看char bucket_name[] = "examplebucket-12500000000";// 开发者访问 COS 服务时拥有的用户维度唯一资源标识,用以标识资源,可在 https://console.cloud.tencent.com/cam/capi 页面获取char appid[] = "12500000000";// 开发者拥有的项目身份ID/密钥,可在 https://console.cloud.tencent.com/cam/capi 页面获取char secret_id[] = "AKIDXXXXXXXX";char secret_key[] = "1A2Z3YYYYYYYYYY";//endpoint 是 COS 访问域名信息(不设置存储桶前缀,访问 COS 时会自动在前面拼接上[bucket]-[appid]), 详情请参见 https://cloud.tencent.com/document/product/436/6224 文档char endpoint[] = "cos.ap-guangzhou.myqcloud.com";// 是否使用自定域名。如果设置为 COS_TRUE ,则访问 COS 时需要将 endpoint 的值修改为自定义域名int is_cname = COS_FALSE;void init_test_config(cos_config_t* config, int is_cname) {cos_str_set(&config->endpoint, endpoint);cos_str_set(&config->access_key_id, secret_id);cos_str_set(&config->access_key_secret, secret_key);cos_str_set(&config->appid, appid);// cos_str_set(&config->sts_token, token); // 使用临时密钥时的 tokenconfig->is_cname = is_cname; // 是否使用自定义域名}void init_test_request_options(cos_request_options_t* options, int is_cname) {options->config = cos_config_create(options->pool);init_test_config(options->config, is_cname);options->ctl = cos_http_controller_create(options->pool, 0);}void log_status(cos_status_t* s) {cos_warn_log("status->code: %d", s->code);if (s->error_code)cos_warn_log("status->error_code: %s", s->error_code);if (s->error_msg)cos_warn_log("status->error_msg: %s", s->error_msg);if (s->req_id)cos_warn_log("status->req_id: %s", s->req_id);}void upload_part_demo(){char object_name[] = "big_file.txt"; // 对象名称char file_path[] = "big_file.txt"; // 本地文件路径cos_pool_t *p = NULL;cos_status_t *s = NULL;cos_request_options_t *options = NULL;cos_string_t bucket;cos_string_t object;cos_string_t upload_id = cos_string("xxxxxxxxxxxxxxxxxxx"); // 替换您自己的uploadidcos_table_t *resp_headers = NULL;int part_num = 1;int64_t pos = 0;int64_t file_length = 0;//创建内存池cos_pool_create(&p, NULL);//初始化请求选项options = cos_request_options_create(p);init_test_request_options(options, is_cname);cos_str_set(&bucket, bucket_name);cos_str_set(&object, file_path);//上传分块int res = COSE_OK;cos_upload_file_t *upload_file = NULL;cos_file_buf_t *fb = cos_create_file_buf(p);res = cos_open_file_for_all_read(p, file_path, fb);if (res != COSE_OK) {cos_error_log("Open read file fail, filename:%s\\n", file_path);return;}file_length = fb->file_last;apr_file_close(fb->file);while(pos < file_length) {upload_file = cos_create_upload_file(p);cos_str_set(&upload_file->filename, file_path);upload_file->file_pos = pos;pos += 2 * 1024 * 1024;upload_file->file_last = pos < file_length ? pos : file_length; //2MBs = cos_upload_part_from_file(options, &bucket, &object, &upload_id,part_num++, upload_file, &resp_headers);if (cos_status_is_ok(s)) {char* etag = NULL;etag = apr_pstrdup(p, (char*)apr_table_get(resp_headers, "ETag"));printf("upload part succeeded, ETag:%s\\n",etag);} else {printf("upload part failed\\n");}}//销毁内存池cos_pool_destroy(p);}int main() {if (cos_http_io_initialize(NULL, 0) != COSE_OK) {exit(1);}upload_part_demo();// cos_http_io_deinitialize lastcos_http_io_deinitialize();return 0;}
参数说明
参数名称 | 参数描述 | 类型 |
options | COS 请求选项 | Struct |
bucket | 存储桶名称,存储桶的命名格式为 BucketName-APPID,此处填写的存储桶名称必须为此格式 | String |
object | Object 名称 | String |
upload_id | 上传任务编号 | String |
part_num | 分块编号 | Int |
upload_file | 待上传本地文件信息 | Struct |
resp_headers | 返回 HTTP 响应消息的头域,可获取到 etag | Struct |
返回结果说明
返回结果 | 描述 | 类型 |
code | 错误码 | Int |
error_code | 错误码内容 | String |
error_msg | 错误码描述 | String |
req_id | 请求消息 ID | String |
使用案例:查询已上传的分块
查询特定分块上传操作中的已上传的块(List Parts)。
方法原型
cos_status_t *cos_list_upload_part(const cos_request_options_t *options,const cos_string_t *bucket,const cos_string_t *object,const cos_string_t *upload_id,cos_list_upload_part_params_t *params,cos_table_t **resp_headers);
请求示例
// COS 的 bucket 名称, [bucket]-[appid], 如: mybucket-1253666666,可在 https://console.cloud.tencent.com/cos5/bucket 查看char bucket_name[] = "examplebucket-12500000000";// 开发者访问 COS 服务时拥有的用户维度唯一资源标识,用以标识资源,可在 https://console.cloud.tencent.com/cam/capi 页面获取char appid[] = "12500000000";// 开发者拥有的项目身份ID/密钥,可在 https://console.cloud.tencent.com/cam/capi 页面获取char secret_id[] = "AKIDXXXXXXXX";char secret_key[] = "1A2Z3YYYYYYYYYY";//endpoint 是 COS 访问域名信息(不设置存储桶前缀,访问 COS 时会自动在前面拼接上[bucket]-[appid]), 详情请参见 https://cloud.tencent.com/document/product/436/6224 文档char endpoint[] = "cos.ap-guangzhou.myqcloud.com";// 是否使用自定域名。如果设置为 COS_TRUE ,则访问 COS 时需要将 endpoint 的值修改为自定义域名int is_cname = COS_FALSE;void init_test_config(cos_config_t* config, int is_cname) {cos_str_set(&config->endpoint, endpoint);cos_str_set(&config->access_key_id, secret_id);cos_str_set(&config->access_key_secret, secret_key);cos_str_set(&config->appid, appid);// cos_str_set(&config->sts_token, token); // 使用临时密钥时的 tokenconfig->is_cname = is_cname; // 是否使用自定义域名}void init_test_request_options(cos_request_options_t* options, int is_cname) {options->config = cos_config_create(options->pool);init_test_config(options->config, is_cname);options->ctl = cos_http_controller_create(options->pool, 0);}void log_status(cos_status_t* s) {cos_warn_log("status->code: %d", s->code);if (s->error_code)cos_warn_log("status->error_code: %s", s->error_code);if (s->error_msg)cos_warn_log("status->error_msg: %s", s->error_msg);if (s->req_id)cos_warn_log("status->req_id: %s", s->req_id);}void list_part_demo(){char object_name[] = "big_file.txt"; // 对象名称cos_pool_t *p = NULL;cos_string_t bucket;cos_string_t object;cos_table_t *resp_headers = NULL;cos_request_options_t *options = NULL;cos_status_t *s = NULL;cos_list_upload_part_params_t *list_upload_param = NULL;cos_pool_create(&p, NULL);options = cos_request_options_create(p);init_test_request_options(options, is_cname);cos_str_set(&bucket, bucket_name);list_upload_param = cos_create_list_upload_part_params(p);list_upload_param->max_ret = 1000;cos_string_t upload_id;cos_str_set(&upload_id,"17224254373527c7f0df239df1ea7416398e5e68b5d6c84967507d64d73db99460bee0aaba"); // 替换您自己的uploadidcos_str_set(&object, object_name);s = cos_list_upload_part(options, &bucket, &object, &upload_id,list_upload_param, &resp_headers);log_status(s);if (cos_status_is_ok(s)) {printf("List upload part succeeded, upload_id::%.*s\\n",upload_id.len, upload_id.data);cos_list_part_content_t *part_content = NULL;cos_list_for_each_entry(cos_list_part_content_t, part_content, &list_upload_param->part_list, node) {printf("part_number = %s, size = %s, last_modified = %s, etag = %s\\n",part_content->part_number.data,part_content->size.data,part_content->last_modified.data,part_content->etag.data);}} else {printf("List upload part failed\\n");}cos_pool_destroy(p);}int main() {if (cos_http_io_initialize(NULL, 0) != COSE_OK) {exit(1);}list_part_demo();// cos_http_io_deinitialize lastcos_http_io_deinitialize();return 0;}
参数说明
参数名称 | 参数描述 | 类型 |
options | COS 请求选项 | Struct |
bucket | 存储桶名称,存储桶的命名格式为 BucketName-APPID,此处填写的存储桶名称必须为此格式 | String |
object | Object 名称 | Struct |
upload_id | 上传任务编号 | String |
params | List Parts 操作参数 | String |
params.part_number_marker | 默认以 UTF-8 二进制顺序列出条目,所有列出条目从 marker 开始 | String |
params.encoding_type | 规定返回值的编码方式 | String |
params.max_ret | 单次返回最大的条目数量,默认1000 | String |
params.truncated | 返回条目是否被截断,'true' 或者 'false' | String |
params.next_part_number_marker | 假如返回条目被截断,则返回 NextMarker 就是下一个条目的起点 | Boolean |
params.part_list | 完成分块的信息 | String |
params.part_list.part_number | 分块编号 | String |
params.part_list.size | 分块大小,单位 Byte | Struct |
params.part_list.etag | 分块的 SHA-1 算法校验值 | String |
params.part_list.last_modified | 分块最后修改时间 | String |
resp_headers | 返回 HTTP 响应消息的头域 | String |
返回结果说明
返回结果 | 描述 | 类型 |
code | 错误码 | Int |
error_code | 错误码内容 | String |
error_msg | 错误码描述 | String |
req_id | 请求消息 ID | String |
使用案例:完成分块上传
完成整个文件的分块上传(Complete Multipart Upload)。
说明:
完成分块上传之后,分块上传任务将删除,任务对应的 uploadId 不再有效。
方法原型
cos_status_t *cos_complete_multipart_upload(const cos_request_options_t *options,const cos_string_t *bucket,const cos_string_t *object,const cos_string_t *upload_id,cos_list_t *part_list,cos_table_t *headers,cos_table_t **resp_headers);
请求示例
// COS 的 bucket 名称, [bucket]-[appid], 如: mybucket-1253666666,可在 https://console.cloud.tencent.com/cos5/bucket 查看char bucket_name[] = "examplebucket-12500000000";// 开发者访问 COS 服务时拥有的用户维度唯一资源标识,用以标识资源,可在 https://console.cloud.tencent.com/cam/capi 页面获取char appid[] = "12500000000";// 开发者拥有的项目身份ID/密钥,可在 https://console.cloud.tencent.com/cam/capi 页面获取char secret_id[] = "AKIDXXXXXXXX";char secret_key[] = "1A2Z3YYYYYYYYYY";//endpoint 是 COS 访问域名信息(不设置存储桶前缀,访问 COS 时会自动在前面拼接上[bucket]-[appid]), 详情请参见 https://cloud.tencent.com/document/product/436/6224 文档char endpoint[] = "cos.ap-guangzhou.myqcloud.com";// 是否使用自定域名。如果设置为 COS_TRUE ,则访问 COS 时需要将 endpoint 的值修改为自定义域名int is_cname = COS_FALSE;void init_test_config(cos_config_t* config, int is_cname) {cos_str_set(&config->endpoint, endpoint);cos_str_set(&config->access_key_id, secret_id);cos_str_set(&config->access_key_secret, secret_key);cos_str_set(&config->appid, appid);// cos_str_set(&config->sts_token, token); // 使用临时密钥时的 tokenconfig->is_cname = is_cname; // 是否使用自定义域名}void init_test_request_options(cos_request_options_t* options, int is_cname) {options->config = cos_config_create(options->pool);init_test_config(options->config, is_cname);options->ctl = cos_http_controller_create(options->pool, 0);}void log_status(cos_status_t* s) {cos_warn_log("status->code: %d", s->code);if (s->error_code)cos_warn_log("status->error_code: %s", s->error_code);if (s->error_msg)cos_warn_log("status->error_msg: %s", s->error_msg);if (s->req_id)cos_warn_log("status->req_id: %s", s->req_id);}void complete_multipart_upload_demo(){char object_name[] = "big_file.txt"; // 对象名称cos_pool_t *p = NULL;cos_status_t *s = NULL;cos_request_options_t *options = NULL;cos_string_t bucket;cos_string_t object;cos_list_upload_part_params_t *params = NULL;cos_list_t complete_part_list;cos_string_t upload_id = cos_string("17224254373527c7f0df239df1ea7416398e5e68b5d6c84967507d64d73db99460bee0aaba"); // 替换您自己的uploadidcos_table_t *resp_headers = NULL;cos_list_part_content_t *part_content = NULL;cos_complete_part_content_t *complete_part_content = NULL;//创建内存池cos_pool_create(&p, NULL);//初始化请求选项options = cos_request_options_create(p);init_test_request_options(options, is_cname);cos_str_set(&bucket, bucket_name);cos_str_set(&object, object_name);//查询已上传分块params = cos_create_list_upload_part_params(p);params->max_ret = 1000;cos_list_init(&complete_part_list);s = cos_list_upload_part(options, &bucket, &object, &upload_id,params, &resp_headers);if (cos_status_is_ok(s)) {printf("List multipart succeeded\\n");} else {printf("List multipart failed\\n");cos_pool_destroy(p);return;}cos_list_for_each_entry(cos_list_part_content_t, part_content, ¶ms->part_list, node) {complete_part_content = cos_create_complete_part_content(p);cos_str_set(&complete_part_content->part_number, part_content->part_number.data);cos_str_set(&complete_part_content->etag, part_content->etag.data);cos_list_add_tail(&complete_part_content->node, &complete_part_list);}//完成分块上传s = cos_complete_multipart_upload(options, &bucket, &object, &upload_id,&complete_part_list, NULL, &resp_headers);if (cos_status_is_ok(s)) {printf("Complete multipart upload from file succeeded, upload_id:%.*s\\n",upload_id.len, upload_id.data);} else {printf("Complete multipart upload from file failed\\n");}//销毁内存池cos_pool_destroy(p);}int main() {if (cos_http_io_initialize(NULL, 0) != COSE_OK) {exit(1);}complete_multipart_upload_demo();// cos_http_io_deinitialize lastcos_http_io_deinitialize();return 0;}
参数说明
参数名称 | 参数描述 | 类型 |
options | COS 请求选项 | Struct |
bucket | 存储桶名称,存储桶的命名格式为 BucketName-APPID,此处填写的存储桶名称必须为此格式 | String |
object | Object 名称 | String |
upload_id | 上传任务编号 | String |
part_list | 完成分块上传的参数 | Struct |
part_list.part_number | 分块编号 | String |
part_list.etag | 分块的 ETag 值,为 sha1 校验值,需要在校验值前后加上双引号,如 "3a0f1fd698c235af9cf098cb74aa25bc" | String |
headers | COS 请求附加头域 | Struct |
resp_headers | 返回 HTTP 响应消息的头域 | Struct |
返回结果说明
返回结果 | 描述 | 类型 |
code | 错误码 | Int |
error_code | 错误码内容 | String |
error_msg | 错误码描述 | String |
req_id | 请求消息 ID | String |
使用案例:终止分块上传
终止一个分块上传操作并删除已上传的分块(Abort Multipart Upload)。
说明:
终止分块上传之后,分块上传任务和已经上传的分块都会被删除,对应的 uploadId 不再有效。
方法原型
cos_status_t *cos_abort_multipart_upload(const cos_request_options_t *options,const cos_string_t *bucket,const cos_string_t *object,cos_string_t *upload_id,cos_table_t **resp_headers);
请求示例
// COS 的 bucket 名称, [bucket]-[appid], 如: mybucket-1253666666,可在 https://console.cloud.tencent.com/cos5/bucket 查看char bucket_name[] = "examplebucket-12500000000";// 开发者访问 COS 服务时拥有的用户维度唯一资源标识,用以标识资源,可在 https://console.cloud.tencent.com/cam/capi 页面获取char appid[] = "12500000000";// 开发者拥有的项目身份ID/密钥,可在 https://console.cloud.tencent.com/cam/capi 页面获取char secret_id[] = "AKIDXXXXXXXX";char secret_key[] = "1A2Z3YYYYYYYYYY";//endpoint 是 COS 访问域名信息(不设置存储桶前缀,访问 COS 时会自动在前面拼接上[bucket]-[appid]), 详情请参见 https://cloud.tencent.com/document/product/436/6224 文档char endpoint[] = "cos.ap-guangzhou.myqcloud.com";// 是否使用自定域名。如果设置为 COS_TRUE ,则访问 COS 时需要将 endpoint 的值修改为自定义域名int is_cname = COS_FALSE;void init_test_config(cos_config_t* config, int is_cname) {cos_str_set(&config->endpoint, endpoint);cos_str_set(&config->access_key_id, secret_id);cos_str_set(&config->access_key_secret, secret_key);cos_str_set(&config->appid, appid);// cos_str_set(&config->sts_token, token); // 使用临时密钥时的 tokenconfig->is_cname = is_cname; // 是否使用自定义域名}void init_test_request_options(cos_request_options_t* options, int is_cname) {options->config = cos_config_create(options->pool);init_test_config(options->config, is_cname);options->ctl = cos_http_controller_create(options->pool, 0);}void log_status(cos_status_t* s) {cos_warn_log("status->code: %d", s->code);if (s->error_code)cos_warn_log("status->error_code: %s", s->error_code);if (s->error_msg)cos_warn_log("status->error_msg: %s", s->error_msg);if (s->req_id)cos_warn_log("status->req_id: %s", s->req_id);}void abort_multipart_upload_demo(){char object_name[] = "big_file.txt"; // 对象名称cos_pool_t *p = NULL;cos_string_t bucket;cos_string_t object;cos_table_t *headers = NULL;cos_table_t *resp_headers = NULL;cos_request_options_t *options = NULL;cos_string_t upload_id;cos_status_t *s = NULL;cos_pool_create(&p, NULL);options = cos_request_options_create(p);init_test_request_options(options, is_cname);headers = cos_table_make(p, 1);cos_str_set(&bucket, bucket_name);cos_str_set(&object, object_name);s = cos_init_multipart_upload(options, &bucket, &object,&upload_id, headers, &resp_headers);log_status(s);if (cos_status_is_ok(s)) {printf("Init multipart upload succeeded, upload_id:%.*s\\n",upload_id.len, upload_id.data);} else {printf("Init multipart upload failed\\n");cos_pool_destroy(p);return;}s = cos_abort_multipart_upload(options, &bucket, &object, &upload_id,&resp_headers);log_status(s);if (cos_status_is_ok(s)) {printf("Abort multipart upload succeeded, upload_id::%.*s\\n",upload_id.len