全部产品
存储与CDN 数据库 安全 应用服务 数加·人工智能 数加·大数据基础服务 互联网中间件 视频服务 开发者工具 解决方案 物联网
对象存储 OSS

上传文件

更新时间:2017-08-23 15:11:07

在OSS中,用户操作的基本数据单元是文件(Object)。单个文件的最大允许大小根据上传数据方式不同而不同,Put Object方式文件最大不能超过5GB,使用分片上传方式文件大小不能超过48.8TB。

OSS C SDK提供了丰富的文件上传接口,用户可以通过以下方式向OSS中上传文件:

  • 简单上传
  • 追加上传
  • 断点续传上传
  • 分片上传

简单上传

从内存中上传数据到OSS

通过oss_put_object_from_buffer接口,可以实现从内存中上传数据到OSS:

  1. void put_object_from_buffer()
  2. {
  3. aos_pool_t *p = NULL;
  4. aos_string_t bucket;
  5. aos_string_t object;
  6. aos_table_t *headers = NULL;
  7. aos_table_t *resp_headers = NULL;
  8. oss_request_options_t *options = NULL;
  9. aos_list_t buffer;
  10. aos_buf_t *content = NULL;
  11. char *str = "test oss c sdk";
  12. aos_status_t *s = NULL;
  13. aos_pool_create(&p, NULL);
  14. /* 创建并初始化options */
  15. options = oss_request_options_create(p);
  16. init_options(options);
  17. aos_str_set(&bucket, "<您的bucket名字>");
  18. aos_str_set(&object, "<您的object名字>");
  19. /* 初始化参数 */
  20. aos_list_init(&buffer);
  21. content = aos_buf_pack(options->pool, str, strlen(str));
  22. aos_list_add_tail(&content->node, &buffer);
  23. /* 上传文件 */
  24. s = oss_put_object_from_buffer(options, &bucket, &object,
  25. &buffer, headers, &resp_headers);
  26. /* 判断是否上传成功 */
  27. if (aos_status_is_ok(s)) {
  28. printf("put object from buffer succeeded\n");
  29. } else {
  30. printf("put object from buffer failed\n");
  31. }
  32. /* 释放资源*/
  33. aos_pool_destroy(p);
  34. }

注:

上传本地文件到OSS

通过oss_put_object_from_file接口,并指定fliepath参数,可以实现上传一个本地文件到OSS:

  1. void put_object_from_file()
  2. {
  3. aos_pool_t *p = NULL;
  4. aos_string_t bucket;
  5. aos_string_t object;
  6. aos_table_t *headers = NULL;
  7. aos_table_t *resp_headers = NULL;
  8. oss_request_options_t *options = NULL;
  9. char *filename = __FILE__;
  10. aos_status_t *s = NULL;
  11. aos_string_t file;
  12. aos_pool_create(&p, NULL);
  13. /* 创建并初始化options */
  14. options = oss_request_options_create(p);
  15. init_options(options);
  16. /* 初始化参数 */
  17. headers = aos_table_make(options->pool, 1);
  18. apr_table_set(headers, OSS_CONTENT_TYPE, "image/jpeg");
  19. aos_str_set(&bucket, "<您的bucket名字>");
  20. aos_str_set(&object, "<您的object名字>");
  21. aos_str_set(&file, filename);
  22. /* 上传文件 */
  23. s = oss_put_object_from_file(options, &bucket, &object, &file,
  24. headers, &resp_headers);
  25. /* 判断是否上传成功 */
  26. if (aos_status_is_ok(s)) {
  27. printf("put object from file succeeded\n");
  28. } else {
  29. printf("put object from file failed\n");
  30. }
  31. /* 释放资源*/
  32. aos_pool_destroy(p);
  33. }

注:

  • 使用该方式上传最大文件不能超过5G。如果超过可以使用分片上传。
  • 完整代码参考:GitHub

追加上传

OSS支持可追加的文件类型,调用时需要指定文件追加的位置,对于新创建文件,这个位置是0;对于已经存在的文件,这个位置必须是追加前文件的长度。

  • 文件不存在时,调用Append Object会创建一个可追加的文件
  • 文件存在时,调用Append Object会向文件末尾追加内容

Append Object以追加写的方式上传文件,通过Append Object操作创建的文件类型为Appendable Object,而通过Put Object上传的文件类型是Normal Object。

从内存中追加数据到OSS

通过oss_append_object_from_buffer接口,可以实现从内存中上传数据到OSS:

  1. void append_object_from_buffer()
  2. {
  3. aos_pool_t *p = NULL;
  4. aos_string_t bucket;
  5. aos_string_t object;
  6. char *str = "test oss c sdk";
  7. aos_status_t *s = NULL;
  8. int64_t position = 0;
  9. aos_table_t *headers1 = NULL;
  10. aos_table_t *headers2 = NULL;
  11. aos_table_t *resp_headers = NULL;
  12. oss_request_options_t *options = NULL;
  13. aos_list_t buffer;
  14. aos_buf_t *content = NULL;
  15. char *next_append_position = NULL;
  16. aos_pool_create(&p, NULL);
  17. /* 创建并初始化options */
  18. options = oss_request_options_create(p);
  19. init_options(options);
  20. /* 初始化参数 */
  21. headers1 = aos_table_make(p, 0);
  22. aos_str_set(&bucket, "<您的bucket名字>");
  23. aos_str_set(&object, "<您的object名字>");
  24. /* 获取起始追加位置 */
  25. s = oss_head_object(options, &bucket, &object, headers1, &resp_headers);
  26. if (aos_status_is_ok(s)) {
  27. next_append_position = (char*)(apr_table_get(resp_headers,
  28. "x-oss-next-append-position"));
  29. position = atoi(next_append_position);
  30. }
  31. /* 追加文件 */
  32. headers2 = aos_table_make(p, 0);
  33. aos_list_init(&buffer);
  34. content = aos_buf_pack(p, str, strlen(str));
  35. aos_list_add_tail(&content->node, &buffer);
  36. s = oss_append_object_from_buffer(options, &bucket, &object,
  37. position, &buffer, headers2, &resp_headers);
  38. /* 判断是否追加成功 */
  39. if (aos_status_is_ok(s))
  40. {
  41. printf("append object from buffer succeeded\n");
  42. } else {
  43. printf("append object from buffer failed\n");
  44. }
  45. /* 释放资源*/
  46. aos_pool_destroy(p);
  47. }

注:

从本地文件追加数据到OSS

通过oss_append_object_from_file接口,并指定fliepath参数, 可以实现将一个本地文件的数据追加到OSS:

  1. void append_object_from_file()
  2. {
  3. aos_pool_t *p = NULL;
  4. aos_string_t bucket;
  5. aos_string_t object;
  6. aos_table_t *headers1 = NULL;
  7. aos_table_t *headers2 = NULL;
  8. aos_table_t *resp_headers = NULL;
  9. oss_request_options_t *options = NULL;
  10. char *filename = __FILE__;
  11. aos_status_t *s = NULL;
  12. aos_string_t file;
  13. int64_t position = 0;
  14. char *next_append_position = NULL;
  15. aos_pool_create(&p, NULL);
  16. /* 创建并初始化options */
  17. options = oss_request_options_create(p);
  18. init_options(options);
  19. /* 初始化参数 */
  20. headers1 = aos_table_make(options->pool, 0);
  21. headers2 = aos_table_make(options->pool, 0);
  22. aos_str_set(&bucket, "<您的bucket名字>");
  23. aos_str_set(&object, "<您的object名字>");
  24. aos_str_set(&file, filename);
  25. /* 获取起始追加位置 */
  26. s = oss_head_object(options, &bucket, &object, headers1, &resp_headers);
  27. if(aos_status_is_ok(s)) {
  28. next_append_position = (char*)(apr_table_get(resp_headers,
  29. "x-oss-next-append-position"));
  30. position = atoi(next_append_position);
  31. }
  32. /* 追加文件 */
  33. s = oss_append_object_from_file(options, &bucket, &object,
  34. position, &file, headers2, &resp_headers);
  35. /* 判断是否追加成功 */
  36. if (aos_status_is_ok(s)) {
  37. printf("append object from file succeeded\n");
  38. } else {
  39. printf("append object from file failed\n");
  40. }
  41. /* 释放资源*/
  42. aos_pool_destroy(p);
  43. }

注:

  • 不能对一个非Appendable Object进行Append Object操作。例如,已经存在一个同名Normal Object时,Append Object调用返回409,错误码ObjectNotAppendable。
  • 对一个已经存在的Appendable Object进行Put Object操作,那么该Appendable Object会被新的Object覆盖,类型变为Normal Object。
  • Head Object操作会返回x-oss-object-type,用于表明Object的类型。对于Appendable Object来说,该值为Appendable。对Appendable Object,Head Object也会返回上述的x-oss-next-append-position和x-oss-hash-crc64ecma。
  • 不能使用Copy Object来拷贝一个Appendable Object,也不能改变它的服务器端加密的属性。可以使用Copy Object来改变用户自定义元信息。
  • 完整代码参考:GitHub

断点续传上传

大文件上传时,网络不稳定或者其它异常发生,则整个上传就会失败。用户不得不重新上传,造成浪费资源;在网络不稳定的情况下,往往要重试多次。断点续传上传,支持并发、断点续传。断点续传上传通过 oss_resumable_clt_params_t 控制并发、断点续传的行为,它有以下参数:

  • part_size 分片大小,从100KB到5GB,单位是byte
  • thread_num 并发线程数,默认为1
  • enable_checkpoint 是否开启断点续传,默认不开启
  • checkpoint_path checkpoint文件的路径,默认放在上传文件目录下{upload_file_path}.cp

断点续传上传的实现原理是,将要上传文件分成若干个分片分别上传,所有分片上传成功后,完成整个文件的上传。在上传的过程中会记录当前上传的进度信息(记录在checkpoint文件中),如果上传过程中某一分片上传失败,再次上传时会从checkpoint文件中记录的断点继续上传。这要求再次调用时要指定与上次相同的checkpoint文件。上传完成后,checkpoint文件会被删除。

  1. void resumable_upload()
  2. {
  3. aos_pool_t *p = NULL;
  4. aos_string_t bucket;
  5. aos_string_t object;
  6. aos_string_t filename;
  7. aos_status_t *s = NULL;
  8. int is_cname = 0;
  9. aos_table_t *headers = NULL;
  10. aos_table_t *resp_headers = NULL;
  11. aos_list_t resp_body;
  12. oss_request_options_t *options = NULL;
  13. oss_resumable_clt_params_t *clt_params;
  14. aos_pool_create(&p, NULL);
  15. options = oss_request_options_create(p);
  16. init_sample_request_options(options, is_cname);
  17. headers = aos_table_make(p, 0);
  18. aos_str_set(&bucket, BUCKET_NAME);
  19. aos_str_set(&object, "my_key.zip");
  20. aos_str_set(&filename, "local_big_file.zip");
  21. aos_list_init(&resp_body);
  22. // 断点续传
  23. clt_params = oss_create_resumable_clt_params_content(p, 1024 * 100, 3, AOS_TRUE, NULL);
  24. s = oss_resumable_upload_file(options, &bucket, &object, &filename, headers, NULL,
  25. clt_params, NULL, &resp_headers, &resp_body);
  26. if (aos_status_is_ok(s)) {
  27. printf("upload succeeded\n");
  28. } else {
  29. printf("upload failed\n");
  30. }
  31. aos_pool_destroy(p);
  32. }

注:

  • 断点续传上传支持设置元信息、上传回调、进度条功能。
  • 完整代码参考:GitHub

分片上传

除了通过简单上传将文件上传到OSS以外,OSS还提供了另外一种上传模式 —— 分片上传。用户可以在如下的应用场景内(但不仅限于此),使用分片上传模式,如:

  • 需要支持断点上传。
  • 上传超过100MB大小的文件。
  • 网络条件较差,和OSS的服务器之间的连接经常断开。
  • 需要流式地上传文件。上传文件之前,无法确定上传文件的大小。

易用接口完成分片上传

为了方便用户完成分片上传,下面代码通过封装后的易用接口oss_upload_file进行分片上传文件操作。

  1. void test_upload_file()
  2. {
  3. aos_pool_t *p = NULL;
  4. aos_string_t bucket;
  5. aos_string_t object;
  6. oss_request_options_t *options = NULL;
  7. aos_status_t *s = NULL;
  8. int part_size = 100 * 1024;
  9. aos_string_t upload_id;
  10. aos_string_t filepath;
  11. aos_pool_create(&p, NULL);
  12. /* 创建并初始化options */
  13. options = oss_request_options_create(p);
  14. init_options(options);
  15. aos_str_set(&bucket, "<您的bucket名字>");
  16. aos_str_set(&object, "<您的object名字>");
  17. aos_str_null(&upload_id);
  18. aos_str_set(&filepath, __FILE__);
  19. /* 分片上传 */
  20. s = oss_upload_file(options, &bucket, &object, &upload_id, &filepath,
  21. part_size, NULL);
  22. /* 判断是否上传成功 */
  23. if (aos_status_is_ok(s)) {
  24. printf("upload file succeeded\n");
  25. } else {
  26. printf("upload file failed\n");
  27. }
  28. /* 释放资源*/
  29. aos_pool_destroy(p);
  30. }

注:

  • 使用oss_upload_file进行分片上传文件操作,如果是一个新的分片上传操作,设置upload_id为NULL,可以通过aos_str_null(&upload_id)实现;如果是对一个已经存在的upload_id进行续传操作,设置upload_id为指定的upload_id_str,可以通过aos_str_set(&upload_id, upload_id_str)实现。
  • 使用oss_upload_file进行分片上传文件操作时,需要指定分片大小, 分片大小要大于100KB。分片号码的范围是1~10000,如果在切分文件时,发现分片号码的范围超出这个范围,oss_upload_file将自动调整分片大小。
  • 使用oss_upload_file进行分片上传文件操作,如果指定的upload_id已经存在,那么本次分片上传的分片大小要和指定upload_id的分片大小保持一致。
  • 完整代码参考:GitHub

分步完成分片上传

分步完成分片上传的好处是灵活,一般的流程如下:

  1. 初始化一个分片上传任务(oss_init_multipart_upload)
  2. 逐个或并行上传分片(oss_upload_part_from_file)
  3. 完成上传(oss_complete_multipart_upload)

初始化

初始化一个分片上传事件

  1. void init_multipart_upload()
  2. {
  3. aos_pool_t *p = NULL;
  4. aos_string_t bucket;
  5. aos_string_t object;
  6. aos_table_t *headers = NULL;
  7. aos_table_t *resp_headers = NULL;
  8. oss_request_options_t *options = NULL;
  9. aos_string_t upload_id;
  10. oss_upload_file_t *upload_file = NULL;
  11. aos_status_t *s = NULL;
  12. oss_list_upload_part_params_t *params = NULL;
  13. aos_list_t complete_part_list;
  14. oss_list_part_content_t *part_content = NULL;
  15. aos_pool_create(&p, NULL);
  16. /* 创建并初始化options */
  17. options = oss_request_options_create(p);
  18. init_options(options);
  19. /* 初始化参数 */
  20. headers = aos_table_make(p, 1);
  21. aos_str_set(&bucket, "<您的bucket名字>");
  22. aos_str_set(&object, "<您的object名字>");
  23. /* 初始化分片上传,获取一个上传ID */
  24. s = oss_init_multipart_upload(options, &bucket, &object,
  25. &upload_id, headers, &resp_headers);
  26. /* 判断是否初始化分片上传成功 */
  27. if (aos_status_is_ok(s)) {
  28. printf("Init multipart upload succeeded, upload_id:%.*s\n",
  29. upload_id.len, upload_id.data);
  30. } else {
  31. printf("Init multipart upload failed, upload_id:%.*s\n",
  32. upload_id.len, upload_id.data);
  33. }
  34. /* 上传每一个分片,代码参考下一节,这里省略*/
  35. /* 完成分片上传,代码参考后面章节,这里省略*/
  36. /* 释放资源*/
  37. aos_pool_destroy(p);
  38. }

注:

  • 返回结果中含有uplolad_id ,它是区分分片上传事件的唯一标识,在后面的操作中,我们将用到它。
  • 上述代码只是演示如何初始化分片上传,只是部分代码,完整的代码参考下面的GitHub链接。
  • 完整代码参考:GitHub
  • 1.0.0版本中的参数顺序是…headers, upload_id…,2.0.0版本中的参数顺序是…upload_id,headers…

本地上传分片

接着,把本地文件分片上传。

  1. void multipart_upload_file()
  2. {
  3. aos_pool_t *p = NULL;
  4. aos_string_t bucket;
  5. aos_string_t object;
  6. int is_cname = 0;
  7. aos_table_t *headers = NULL;
  8. aos_table_t *complete_headers = NULL;
  9. aos_table_t *resp_headers = NULL;
  10. oss_request_options_t *options = NULL;
  11. aos_string_t upload_id;
  12. oss_upload_file_t *upload_file = NULL;
  13. aos_status_t *s = NULL;
  14. oss_list_upload_part_params_t *params = NULL;
  15. aos_list_t complete_part_list;
  16. oss_list_part_content_t *part_content = NULL;
  17. oss_complete_part_content_t *complete_part_content = NULL;
  18. int part_num1 = 1;
  19. int part_num2 = 2;
  20. aos_pool_create(&p, NULL);
  21. /* 创建并初始化options */
  22. options = oss_request_options_create(p);
  23. init_options(options);
  24. /* 初始化参数 */
  25. headers = aos_table_make(p, 1);
  26. resp_headers = aos_table_make(options->pool, 5);
  27. aos_str_set(&bucket, "<您的bucket名字>");
  28. aos_str_set(&object, "<您的object名字>");
  29. /* 初始化分片上传,获取upload id,代码参考前面章节,这里省略*/
  30. /* 上传第一个分片 */
  31. upload_file = oss_create_upload_file(p);
  32. aos_str_set(&upload_file->filename, MULTIPART_UPLOAD_FILE_PATH);
  33. upload_file->file_pos = 0;
  34. upload_file->file_last = 200 * 1024; //200k
  35. s = oss_upload_part_from_file(options, &bucket, &object, &upload_id,
  36. part_num1, upload_file, &resp_headers);
  37. /* 判断是否上传分片成功 */
  38. if (aos_status_is_ok(s)) {
  39. printf("Multipart upload from file succeeded\n");
  40. } else {
  41. printf("Multipart upload from file failed\n");
  42. }
  43. /* 上传第二个分片 */
  44. upload_file->file_pos = 200 *1024;//remain content start pos
  45. upload_file->file_last = get_file_size(MULTIPART_UPLOAD_FILE_PATH);
  46. s = oss_upload_part_from_file(options, &bucket, &object, &upload_id,
  47. part_num2, upload_file, &resp_headers);
  48. /* 判断是否上传分片成功 */
  49. if (aos_status_is_ok(s)) {
  50. printf("Multipart upload from file succeeded\n");
  51. } else {
  52. printf("Multipart upload from file failed\n");
  53. }
  54. /* 完成分片上传,代码参考下一章节,这里省略*/
  55. /* 释放资源*/
  56. aos_pool_destroy(p);
  57. }

上面程序的核心是调用oss_upload_part_from_file接口来上传每一个分片。

注:

  • oss_upload_part_from_file接口要求除最后一个分片以外,其他的分片大小都要大于100KB。
  • 分片号码的范围是1~10000。如果超出这个范围,OSS将返回InvalidArgument的错误码。
  • 每次上传分片时都要把流定位到此次上传分片开头所对应的位置。
  • 上述代码只是演示如何初始化分片上传,只是部分代码,完整的代码参考下面的GitHub链接。
  • 完整代码参考:GitHub

获取已上传的分片,完成分片上传

  1. void complete_multipart_upload()
  2. {
  3. aos_pool_t *p = NULL;
  4. aos_string_t bucket;
  5. aos_string_t object;
  6. aos_table_t *complete_headers = NULL;
  7. aos_table_t *resp_headers = NULL;
  8. oss_request_options_t *options = NULL;
  9. aos_string_t upload_id;
  10. aos_status_t *s = NULL;
  11. oss_list_upload_part_params_t *params = NULL;
  12. aos_list_t complete_part_list;
  13. oss_list_part_content_t *part_content = NULL;
  14. oss_complete_part_content_t *complete_part_content = NULL;
  15. aos_pool_create(&p, NULL);
  16. /* 创建并初始化options */
  17. options = oss_request_options_create(p);
  18. init_options(options);
  19. /* 初始化参数 */
  20. headers = aos_table_make(p, 1);
  21. resp_headers = aos_table_make(options->pool, 5);
  22. aos_str_set(&bucket, "<您的bucket名字>");
  23. aos_str_set(&object, "<您的object名字>");
  24. /* 初始化分片上传,获取一个Upload Id,代码参考上面章节,这里省略*/
  25. /* 上传每个分片,代码参考上面章节,这里省略*/
  26. /* 获取已经上传的分片
  27. * 调用oss_complete_multipart_upload接口时需要每个分片的ETag值,这个值有两种获取途径:
  28. * 第一种是上传每个分片的时候,返回结果里面会包含这个分片的ETag值,可以保存下来,等后面使用;
  29. * 第二种是通过调用oss_list_upload_part接口获取已经上传的分片的ETag值。
  30. * 下面演示的是第二种方式
  31. */
  32. params = oss_create_list_upload_part_params(p);
  33. params->max_ret = 1000;
  34. aos_list_init(&complete_part_list);
  35. s = oss_list_upload_part(options, &bucket, &object, &upload_id,
  36. params, &resp_headers);
  37. /* 判断是否获取分片列表成功 */
  38. if (aos_status_is_ok(s)) {
  39. printf("List multipart succeeded\n");
  40. } else {
  41. printf("List multipart failed\n");
  42. }
  43. aos_list_for_each_entry(part_content, &params->part_list, node) {
  44. complete_part_content = oss_create_complete_part_content(p);
  45. aos_str_set(&complete_part_content->part_number,
  46. part_content->part_number.data);
  47. aos_str_set(&complete_part_content->etag, part_content->etag.data);
  48. aos_list_add_tail(&complete_part_content->node, &complete_part_list);
  49. }
  50. /* 完成分片上传 */
  51. s = oss_complete_multipart_upload(options, &bucket, &object, &upload_id,
  52. &complete_part_list, complete_headers, &resp_headers);
  53. /* 判断完成分片上传是否成功 */
  54. if (aos_status_is_ok(s)) {
  55. printf("Complete multipart upload from file succeeded, upload_id:%.*s\n",
  56. upload_id.len, upload_id.data);
  57. } else {
  58. printf("Complete multipart upload from file failed\n");
  59. }
  60. /* 释放资源 */
  61. aos_pool_destroy(p);
  62. }

注:

  • 2.0.0相对于1.0.0版本,oss_complete_multipart_upload接口增加了headers参数,用来在完成时修改headers值
  • 完整代码参考:GitHub

取消分片上传事件

  1. void abort_multipart_upload()
  2. {
  3. aos_pool_t *p = NULL;
  4. aos_string_t bucket;
  5. aos_string_t object;
  6. aos_table_t *headers = NULL;
  7. aos_table_t *resp_headers = NULL;
  8. oss_request_options_t *options = NULL;
  9. aos_string_t upload_id;
  10. aos_status_t *s = NULL;
  11. aos_pool_create(&p, NULL);
  12. /* 创建并初始化options */
  13. options = oss_request_options_create(p);
  14. init_options(options);
  15. /* 初始化参数 */
  16. headers = aos_table_make(p, 1);
  17. aos_str_set(&bucket, "<您的bucket名字>");
  18. aos_str_set(&object, "<您的object名字>");
  19. /* 初始化分片上传,获取一个Upload Id*/
  20. s = oss_init_multipart_upload(options, &bucket, &object,
  21. &upload_id, headers, &resp_headers);
  22. if (aos_status_is_ok(s)) {
  23. printf("Init multipart upload succeeded, upload_id:%.*s\n",
  24. upload_id.len, upload_id.data);
  25. } else {
  26. printf("Init multipart upload failed\n");
  27. }
  28. /* 取消这次分片上传 */
  29. s = oss_abort_multipart_upload(options, &bucket, &object, &upload_id,
  30. &resp_headers);
  31. /* 判断取消分片上传是否成功 */
  32. if (aos_status_is_ok(s)) {
  33. printf("Abort multipart upload succeeded, upload_id::%.*s\n",
  34. upload_id.len, upload_id.data);
  35. } else {
  36. printf("Abort multipart upload failed\n");
  37. }
  38. /* 释放资源 */
  39. aos_pool_destroy(p);
  40. }

注:

  • 当一个分片上传事件被中止后,就不能再使用这个upload_id做任何操作,已经上传的分片数据也会被删除。
  • 完整代码参考:GitHub

设置元信息

文件元信息(Object Meta),是对用户上传到OSS的文件的属性描述,分为两种:HTTP标准属性(HTTP Headers)和用户自定义元信息(User Meta)。 文件元信息可以在上传(流上传、文件上传、追加上传、分片上传、断点续传),或拷贝时设置。元信息的名称大小写不敏感。更多文件元信息的介绍,请参看文件元信息

HTTP标准属性

常用的HTTP标准属性说明如下,更详细的说明请参考RFC2616

名称 描述 默认值
Content-MD5 文件数据校验,设置了该值后OSS会启用文件内容MD5校验,把您提供的MD5与文件的MD5比较,不一致会返回错误
Content-Type 文件的MIME,定义文件的类型及网页编码,决定浏览器将以什么形式、什么编码读取文件。如果用户没有指定则根据Key或文件名的扩展名生成,如果没有扩展名则填默认值 application/octet-stream
Content-Disposition 指示MIME用户代理如何显示附加的文件,打开或下载,及文件名称
Content-Length 上传的数据的长度,超过长度的数据会被截断,不足为实际值 数据的实际长度
Expires 缓存过期时间,OSS未使用,格式是格林威治时间(GMT)
Cache-Control 指定该Object被下载时的网页的缓存行为
Expect HTTP客户端期望特定的行为,目前支持100-continue libcurl实现相关
Transfer-Encoding 传输数据时候编码方式,目前支持chunked libcurl实现相关
  1. void put_object_from_file()
  2. {
  3. aos_pool_t *p = NULL;
  4. aos_string_t bucket;
  5. aos_string_t object;
  6. aos_table_t *headers = NULL;
  7. aos_table_t *resp_headers = NULL;
  8. oss_request_options_t *options = NULL;
  9. char *filename = __FILE__;
  10. aos_status_t *s = NULL;
  11. aos_string_t file;
  12. aos_pool_create(&p, NULL);
  13. /* 创建并初始化options */
  14. options = oss_request_options_create(p);
  15. init_options(options);
  16. /* 初始化参数 */
  17. headers = aos_table_make(options->pool, 2);
  18. apr_table_set(headers, OSS_CONTENT_TYPE, "image/jpeg");
  19. apr_table_set(headers, OSS_CONTENT_MD5, "eB5eJF1ptWaXm4bijSPyxw==");
  20. aos_str_set(&bucket, "<您的bucket名字>");
  21. aos_str_set(&object, "<您的object名字>");
  22. aos_str_set(&file, filename);
  23. /* 上传文件 */
  24. s = oss_put_object_from_file(options, &bucket, &object, &file,
  25. headers, &resp_headers);
  26. /* 判断是否上传成功 */
  27. if (aos_status_is_ok(s)) {
  28. printf("put object from file succeeded\n");
  29. } else {
  30. printf("put object from file failed\n");
  31. }
  32. /* 释放资源*/
  33. aos_pool_destroy(p);
  34. }

注:

  • 数据、文件MD5值的计算请参看Put Object
  • HTTP标准属性会改变数据传输行为,请在明确知晓其行为后设置

用户自定义元信息

为了便于用户对文件进行更多描述,OSS中规定所有以x-oss-meta-为前缀的参数视为User Meta,一个文件可以有多个类似的参数。User Meta会在下载GetObjectHeadObject的时,在HTTP头部中返回。

  1. void put_object_from_file()
  2. {
  3. aos_pool_t *p = NULL;
  4. aos_string_t bucket;
  5. aos_string_t object;
  6. aos_table_t *headers = NULL;
  7. aos_table_t *resp_headers = NULL;
  8. oss_request_options_t *options = NULL;
  9. char *filename = __FILE__;
  10. aos_status_t *s = NULL;
  11. aos_string_t file;
  12. aos_pool_create(&p, NULL);
  13. /* 创建并初始化options */
  14. options = oss_request_options_create(p);
  15. init_options(options);
  16. /* 初始化参数 */
  17. headers = aos_table_make(options->pool, 4);
  18. apr_table_set(headers, OSS_CONTENT_TYPE, "image/jpeg");
  19. apr_table_set(headers, OSS_CONTENT_MD5, "eB5eJF1ptWaXm4bijSPyxw==");
  20. apr_table_set(headers, "x-oss-meta-author", "mingdi");
  21. apr_table_set(headers, "x-oss-meta-category", "computer");
  22. aos_str_set(&bucket, "<您的bucket名字>");
  23. aos_str_set(&object, "<您的object名字>");
  24. aos_str_set(&file, filename);
  25. /* 上传文件 */
  26. s = oss_put_object_from_file(options, &bucket, &object, &file,
  27. headers, &resp_headers);
  28. /* 判断是否上传成功 */
  29. if (aos_status_is_ok(s)) {
  30. printf("put object from file succeeded\n");
  31. } else {
  32. printf("put object from file failed\n");
  33. }
  34. /* 释放资源*/
  35. aos_pool_destroy(p);
  36. }

上传回调

OSS在上传文件完成的时,可以提供回调(Callback)给应用服务器。用户只需要在发送给OSS的请求中携带相应的回调参数,即能实现回调。支持上传回调接口有:PutObject、PostObject、CompleteMultipartUpload。您想了解上传回调的更详细信息,请参考上传回调。下面以PutObject为例说明上传回调的用法。

  1. void put_object_from_buffer_with_callback()
  2. {
  3. aos_pool_t *p = NULL;
  4. char *str = "test oss c sdk";
  5. aos_status_t *s = NULL;
  6. int is_cname = 0;
  7. aos_string_t bucket;
  8. aos_string_t object;
  9. aos_table_t *headers = NULL;
  10. oss_request_options_t *options = NULL;
  11. aos_table_t *resp_headers = NULL;
  12. aos_list_t resp_body;
  13. aos_list_t buffer;
  14. aos_buf_t *content;
  15. char *buf = NULL;
  16. int64_t len = 0;
  17. int64_t size = 0;
  18. int64_t pos = 0;
  19. char b64_buf[1024];
  20. int b64_len;
  21. /* JSON format */
  22. char *callback = "{"
  23. "\"callbackUrl\":\"http://callback.oss-demo.com:23450\","
  24. "\"callbackHost\":\"oss-cn-hangzhou.aliyuncs.com\","
  25. "\"callbackBody\":\"bucket=${bucket}&object=${object}&size=${size}&mimeType=${mimeType}\","
  26. "\"callbackBodyType\":\"application/x-www-form-urlencoded\""
  27. "}";
  28. /* init sample */
  29. aos_pool_create(&p, NULL);
  30. options = oss_request_options_create(p);
  31. init_sample_request_options(options, is_cname);
  32. aos_str_set(&bucket, BUCKET_NAME);
  33. aos_str_set(&object, OBJECT_NAME);
  34. aos_list_init(&resp_body);
  35. aos_list_init(&buffer);
  36. content = aos_buf_pack(options->pool, str, strlen(str));
  37. aos_list_add_tail(&content->node, &buffer);
  38. /* put call into header */
  39. b64_len = aos_base64_encode((unsigned char*)callback, strlen(callback), b64_buf);
  40. b64_buf[b64_len] = '\0';
  41. headers = aos_table_make(p, 1);
  42. apr_table_set(headers, OSS_CALLBACK, b64_buf);
  43. /* test put object */
  44. s = oss_do_put_object_from_buffer(options, &bucket, &object, &buffer,
  45. headers, NULL, NULL, &resp_headers, &resp_body);
  46. if (aos_status_is_ok(s)) {
  47. printf("put object from buffer succeeded\n");
  48. } else {
  49. printf("put object from buffer failed\n");
  50. }
  51. /* get buffer len */
  52. len = aos_buf_list_len(&resp_body);
  53. buf = (char *)aos_pcalloc(p, (apr_size_t)(len + 1));
  54. buf[len] = '\0';
  55. /* copy buffer content to memory */
  56. aos_list_for_each_entry(aos_buf_t, content, &resp_body, node) {
  57. size = aos_buf_size(content);
  58. memcpy(buf + pos, content->pos, (size_t)size);
  59. pos += size;
  60. }
  61. aos_pool_destroy(p);
  62. }

注:

进度条

OSS C SDK支持进度条功能,指示上传/下载的进度。下面的代码以PutObject为例,说明进度条功能的使用方法。

  1. void percentage(int64_t consumed_bytes, int64_t total_bytes)
  2. {
  3. assert(total_bytes >= consumed_bytes);
  4. printf("%%%" APR_INT64_T_FMT "\n", consumed_bytes * 100 / total_bytes);
  5. }
  6. void put_and_get_from_file_with_progress()
  7. {
  8. aos_pool_t *p = NULL;
  9. aos_status_t *s = NULL;
  10. int is_cname = 0;
  11. aos_string_t bucket;
  12. aos_string_t object;
  13. aos_string_t filename;
  14. oss_request_options_t *options = NULL;
  15. aos_table_t *resp_headers = NULL;
  16. aos_list_t resp_body;
  17. char *download_filename = "get_object_to_local_file.txt";
  18. /* init test*/
  19. aos_pool_create(&p, NULL);
  20. options = oss_request_options_create(p);
  21. init_sample_request_options(options, is_cname);
  22. aos_str_set(&bucket, BUCKET_NAME);
  23. aos_str_set(&object, OBJECT_NAME);
  24. aos_str_set(&filename, __FILE__);
  25. aos_list_init(&resp_body);
  26. /* put object */
  27. s = oss_do_put_object_from_file(options, &bucket, &object, &filename, NULL, NULL, percentage, &resp_headers, &resp_body);
  28. if (aos_status_is_ok(s)) {
  29. printf("put object from file succeeded\n");
  30. } else {
  31. printf("put object from file failed\n");
  32. aos_pool_destroy(p);
  33. return;
  34. }
  35. aos_pool_destroy(p);
  36. }

注:

  • oss_do_put_object_from_buffer、oss_do_put_object_from_file、oss_do_append_object_from_buffer、oss_do_append_object_from_file、oss_do_upload_part_from_buffer、oss_do_upload_part_from_file、oss_resumable_upload_file支持进度条功能,代码请参考:GitHub
本文导读目录