使用oss c sdk自定义上传和下载callback

       前段时间使用阿里云官网提供的OSS C SDK上传和下载数据,想在上传和下载过程中对数据进行一些简单的自定义预处理,看了一下oss c sdk的具体实现,大致了解如何通过自定义上传和下载的callback达到上述目的,这里做一个简单的分享。

       OSS C SDK在上传和下载数据时使用了CURL进行通信,之前简单学习过CURL的一些知识,知道CURL提供了一系列Callback,在上传下载时对数据进行一些处理,大家感兴趣的话可以参考: http://curl.haxx.se/libcurl/c/curl_easy_setopt.html 。OSS C SDK针对OSS的常用场景,对用户暴露了两个最基本的Callback:CURLOPT_WRITEFUNCTION 和 CURLOPT_READFUNCTION。结合OSS C SDK使用这两个Callback实现上传数据和下载数据,可以大致了解整个过程。

1、上传数据

      OSS C SDK上传数据提供了两种方式:从memory读取、从文件读取。以从文件读取数据为例,我们看一下如何利用Callback实现从文件读取数据上传到OSS的。 
首先,我们熟悉oss c sdk中使用的一些数据结构: 
struct aos_http_request_s { 
    char *host; 
    uint8_t port; 
    char *signed_url; 
 
    http_method_e method; 
    char *uri; 
    char *resource; 
    aos_table_t *headers; 
    aos_table_t *query_params; 
 
    aos_list_t body; 
    int64_t body_len; 
    char *file_path; 
    aos_file_buf_t *file_buf; 
 
    aos_pool_t *pool; 
    void *user_data; 
    aos_read_http_body_pt read_body; 
 
    aos_http_body_type_e type; 
}; 
 
typedef enum { 
    BODY_IN_MEMORY = 0, 
    BODY_IN_FILE, 
    BODY_IN_CALLBACK 
} aos_http_body_type_e; 
 
typedef int (*aos_read_http_body_pt)(aos_http_request_t *req, char *buffer, int len); 

OSS C SDK提供了oss_put_object_from_file接口用于从文件读取数据上传到OSS,重点看一下oss_write_request_body_from_file的实现: 
 
int oss_write_request_body_from_file(aos_pool_t *p, const aos_string_t *filename, aos_http_request_t *req) 

    int res = AOSE_OK; 
    aos_file_buf_t *fb = aos_create_file_buf(p); 
    res = aos_open_file_for_all_read(p, filename->data, fb); 
    if (res != AOSE_OK) { 
        aos_error_log("Open read file fail, filename:%s\n", filename->data); 
        return res; 
    } 
 
    req->body_len = fb->file_last; 
    req->file_path = filename->data; 
    req->file_buf = fb; 
    req->type = BODY_IN_FILE; 
    req->read_body = aos_read_http_body_file; 
 
    return res; 

 

和上面的aos_http_request_s数据结构联系起来,可以看到在这里设置读取文件的相关信息的。接下来看一下这些设置如何和CURL提供的Callback联系上。

aos_http_transport_t *aos_curl_http_transport_create(aos_pool_t *p) 

    aos_func_u func; 
    aos_curl_http_transport_t *t; 
 
    t = (aos_curl_http_transport_t *)aos_pcalloc(p, sizeof(aos_curl_http_transport_t)); 
 
    t->pool = p; 
    t->options = aos_default_http_transport_options; 
    t->cleanup = aos_fstack_create(p, 5); 
 
    func.func1 = (aos_func1_pt)aos_transport_cleanup; 
    aos_fstack_push(t->cleanup, t, func, 1); 
 
    t->curl = aos_request_get(); 
    func.func1 = (aos_func1_pt)request_release; 
    aos_fstack_push(t->cleanup, t->curl, func, 1); 
 
    t->header_callback = aos_curl_default_header_callback; 
   t->read_callback = aos_curl_default_read_callback; 
    t->write_callback = aos_curl_default_write_callback; 
 
    return (aos_http_transport_t *)t; 

 
size_t aos_curl_default_read_callback(char *buffer, size_t size, size_t nitems, void *instream) 

    int len; 
    int bytes; 
    aos_curl_http_transport_t *t; 
 
    t = (aos_curl_http_transport_t *)(instream); 
    len = size * nitems; 
 
    if (t->controller->error_code != AOSE_OK) { 
        aos_debug_log("abort read callback."); 
        return CURL_READFUNC_ABORT; 
    } 
 
    if ((bytes = t->req->read_body(t->req, buffer, len)) < 0) { 
        aos_debug_log("read body failure, %d.", bytes); 
        t->controller->error_code = AOSE_READ_BODY_ERROR; 
        t->controller->reason = "read body failure."; 
        return CURL_READFUNC_ABORT; 
    } 
 
    aos_move_transport_state(t, TRANS_STATE_BODY_OUT); 
 
    return bytes; 

 
int aos_curl_transport_setup(aos_curl_http_transport_t *t) 

     ... 
     curl_easy_setopt_safe(CURLOPT_READFUNCTION, t->read_callback); 
     ... 

 
红色部分基本已经说明了OSS C SDK如何调用CURL提供的CURLOPT_READFUNCTION了。参考OSS C SDK上传数据的实现大概也就知道如何对上传数据做一些简单的自定义了。

2、下载数据

下载数据常见的方式有两种:下载数据到memory、下载数据到文件。以下载数据到文件中为例,OSS C SDK使用CURL提供的Callback方式实现了数据下载。首先,熟悉一下OSS C SDK中使用的一些数据结构: 
 
struct aos_http_response_s { 
    int status; 
    aos_table_t *headers; 
 
    aos_list_t body; 
    int64_t body_len; 
    char *file_path; 
    aos_file_buf_t* file_buf; 
    int64_t content_length; 
 
    aos_pool_t *pool; 
    void *user_data; 
    aos_write_http_body_pt write_body; 
    aos_http_body_type_e type; 
}; 
 
typedef enum {      
    BODY_IN_MEMORY = 0,      
    BODY_IN_FILE,      
    BODY_IN_CALLBACK  
} aos_http_body_type_e; 
 
typedef int (*aos_write_http_body_pt)(aos_http_response_t *resp, const char *buffer, int len); 
 
       OSS C SDK提供了oss_get_object_to_file接口用于将OSS上的数据下载到本地文件中。重点看一下这个函数中oss_init_read_response_body_to_file函数的实现: 
 
int oss_init_read_response_body_to_file(aos_pool_t *p, const aos_string_t *filename, aos_http_response_t *resp) 

    int res = AOSE_OK; 
    aos_file_buf_t *fb = aos_create_file_buf(p); 
    res = aos_open_file_for_write(p, filename->data, fb); 
    if (res != AOSE_OK) { 
        aos_error_log("Open write file fail, filename:%s\n", filename->data); 
        return res; 
    } 
    resp->file_path = filename->data; 
    resp->file_buf = fb; 
    resp->write_body = aos_write_http_body_file; 
    resp->type = BODY_IN_FILE; 

    return res; 

 
    这部分和上面的aos_http_response_s数据结构联系起来,可以设置将下载数据写入本地文件。接下来看一下这些设置如何和CURL提供的Callback联系上。
aos_http_transport_t *aos_curl_http_transport_create(aos_pool_t *p) {      
    aos_func_u func;      
    aos_curl_http_transport_t *t;  
    
    t = (aos_curl_http_transport_t *)aos_pcalloc(p, sizeof(aos_curl_http_transport_t));  
    
    t->pool = p;     
    t->options = aos_default_http_transport_options;      
    t->cleanup = aos_fstack_create(p, 5);  
   
    func.func1 = (aos_func1_pt)aos_transport_cleanup;      
    aos_fstack_push(t->cleanup, t, func, 1);  
     
    t->curl = aos_request_get();      
    func.func1 = (aos_func1_pt)request_release;      
    aos_fstack_push(t->cleanup, t->curl, func, 1);  
     
    t->header_callback = aos_curl_default_header_callback;    
    t->read_callback = aos_curl_default_read_callback;     
    t->write_callback = aos_curl_default_write_callback;      
 
 
    return (aos_http_transport_t *)t;  

 
size_t aos_curl_default_write_callback(char *ptr, size_t size, size_t nmemb, void *userdata){ 
    int len;    int bytes; 
    aos_curl_http_transport_t *t; 
 
    t = (aos_curl_http_transport_t *)(userdata);    
    len = size * nmemb; 
 
    if (t->controller->first_byte_time == 0) { 
        t->controller->first_byte_time = apr_time_now();   
    } 
 
    aos_curl_transport_headers_done(t); 
 
    if (t->controller->error_code != AOSE_OK) { 
        aos_debug_log("write callback abort");         
        return 0; 
    } 
 
    if (t->resp->status < 200 || t->resp->status > 299) { 
        bytes = aos_write_http_body_memory(t->resp, ptr, len);         
        assert(bytes == len); 
        aos_move_transport_state(t, TRANS_STATE_BODY_IN);        
        return bytes; 
    } 
 
    if (t->resp->type == BODY_IN_MEMORY && t->resp->body_len >= (int64_t)t->controller->options->max_memory_size) {         
         t->controller->reason = apr_psprintf(t->pool,  
              "receive body too big, current body size: %" APR_INT64_T_FMT ", max memory size: %" APR_INT64_T_FMT,  t->resp->body_len, t->controller->options->max_memory_size); 
        t->controller->error_code = AOSE_OVER_MEMORY; 
        aos_error_log("error reason:%s, ", t->controller->reason); 
        return 0; 
    } 
    if ((bytes = t->resp->write_body(t->resp, ptr, len)) < 0) { 
        aos_debug_log("write body failure, %d.", bytes); 
        t->controller->error_code = AOSE_WRITE_BODY_ERROR; 
        t->controller->reason = "write body failure."; 
        return 0; 
    } 
    aos_move_transport_state(t, TRANS_STATE_BODY_IN); 
    return bytes; 

 
int aos_curl_transport_setup(aos_curl_http_transport_t *t) { 
     ... 
     curl_easy_setopt_safe(CURLOPT_WRITEFUNCTION, t->write_callback); 
    ... 

红色部分基本说明了oss c sdk如何调用CURL提供的CURLOPT_WRITEFUNCTION了。

       参考OSS C SDK使用CURL进行数据上传和下载的实现,能够根据自己的需求自定义数据上传和下载的Callback,对数据进行一些预处理。  

时间: 2024-09-20 00:50:00

使用oss c sdk自定义上传和下载callback的相关文章

利用Wireshark和OSS的API文档简单实现上传和下载

背景及目的 由于各个开发者使用的开发语言可能在官方SDK找不到相应的语言版本,就必须自主开发SDK. 本文根据wireshark和API文档,来简单实现上传和下载的请求,给需要自主开发的开发者提供一个简单的示例. 准备工作 安装wireshark 官网地址:https://www.wireshark.org/download.html 找到合适的平台及版本,下载并安装. 找到OSS的API文档 官网地址:https://help.aliyun.com/document_detail/oss/ap

Android高效率编码-第三方SDK详解系列(二)——Bmob后端云开发,实现登录注册,更改资料,修改密码,邮箱验证,上传,下载,推送消息,缩略图加载等功能

Android高效率编码-第三方SDK详解系列(二)--Bmob后端云开发,实现登录注册,更改资料,修改密码,邮箱验证,上传,下载,推送消息,缩略图加载等功能 我的本意是第二篇写Mob的shareSDK分享组件的,奈何需要去注册各平台的账号,还要审核,有些审核还挺久,就没办法,改为写这个Bmob了,相信大家对Bmob都是挺期待的吧,因为他作为Android后端的实现很好的支持,国内很多软件都在使用它,他的功能也是特别神奇,这里就不一一细说了,我们用实际的例子来见证他的神奇 官网:http://w

FCKeditor 自定义上传目录和自动生成文件名方法

FCKeditor 自定义上传目录和自动生成文件名方法 使用用FCKeditor的上传功能,我们会发现上传后的文件名和本地的是一样的,不会自动更改文件名,这样有时候本地是中文文件名的时候就不是太好了.下面是我对FCKeditor.NET源文件的修改,使上传文件自动生成随机文件名,而且上传目录根据当前时间归类,这样方便管理! 下面使用的是FCKeditor.NET 2.6.3 版. 1.根据当前时间设置上传目录 打开FileBrowserConfig.cs文件,在119行(userFilesPat

Maven自定义上传第三方包到3rd party(第三方无依赖jar和本地扩展类加入maven统一管理)

Maven自定义上传第三方包到3rd party(第三方无依赖jar和本地扩展类加入maven统一管理) 注:如果图片太小,则可以下载查看,CSDN,不提供点击放大! 1:用浏览器登陆nexus服务器(此处为本地): http://localhost:8081/nexus/ admin admin123 2:第三方依赖加入: Log in到nexus中,如下图: 3:手动设置填写:GroupId,Artifact,Version: 4:点击:Select Artifact(s) for Uplo

FreetextBox3.1.6 自定义上传代码修改

问题描述 在网上找了好久的资料.找到了一份3.1.6的自定义上传代码,结果图片可以上传,但是上传的图片不会即时的显示在freetextbox的编辑器里代码如下:<scripttype="text/javascript">FTB_FreeTextBox.prototype.InsertPureSrc=function(imgSrc){if(imgSrc!=''){this.ExecuteCommand('insertimage',null,imgSrc);}}function

与众不同 windows phone (13) - Background Task(后台任务)之后台文件传输(上传和下载)

原文:与众不同 windows phone (13) - Background Task(后台任务)之后台文件传输(上传和下载) [索引页][源码下载] 与众不同 windows phone (13) - Background Task(后台任务)之后台文件传输(上传和下载) 作者:webabcd 介绍与众不同 windows phone 7.5 (sdk 7.1) 之后台任务 后台文件传输(下载) 后台文件传输(上传) 示例1.演示如何实现后台文件传输(下载)BackgroundTransfe

上传或下载当文件名包含有特殊字符&amp;quot;#&amp;quot;的处理

http://www.cnblogs.com/luointer123/archive/2010/03/10/1682728.html 在上传或下载文件时,当文件名包含有"#"特殊字符时,上传以后的文件会被改名字,造成下载也下载不了. 如类似以下的代码:             Uri uri = new Uri(targetUrl);//targetUrl对应文件的绝对路径             System.Net.HttpWebRequest request = (HttpWeb

MyBatis与SpringMVC相结合实现文件上传、下载功能_java

环境:maven+SpringMVC + Spring + MyBatis + MySql 本文主要说明如何使用input上传文件到服务器指定目录,或保存到数据库中:如何从数据库下载文件,和显示图像文件并实现缩放. 将文件存储在数据库中,一般是存文件的byte数组,对应的数据库数据类型为blob. 首先要创建数据库,此处使用MySql数据库. 注意:文中给出的代码多为节选重要片段,并不齐全. 1. 前期准备 使用maven创建一个springMVC+spring+mybatis+mysql的项目

JavaWeb实现文件上传与下载实例详解_java

 在Web应用程序开发中,文件上传与下载功能是非常常用的功能,下面通过本文给大家介绍JavaWeb实现文件上传与下载实例详解. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用Servlet获取上传文件的输入流然后再解析里面的请求参数是比较麻烦,所以一般选择采用apache的开源工具common-fileupload这个文件上传组件.这个common-fileupload上传组件的jar包可以去apache官网上面下载,common-fileupload是依赖于