开发者社区> 问答> 正文

oss c sdk利用CURL提供的Callback实现上传

前面分享了oss c sdk中提供了一些接口方便用户设置CURL的一些参数,以及查看使用oss c sdk后上传数据等操作的一些简单性能参数的方法。
相信对CURL有一定了解的用户知道CURL提供了一系列Callback,方便用户在CURL上传下载时对数据进行一些处理,大家感兴趣的话可以参考: http://curl.haxx.se/libcurl/c/curl_easy_setopt.html 。oss c sdk针对OSS的常用场景,对用户暴露了两个最基本的Callback: CURLOPT_WRITEFUNCTION 和 CURLOPT_READFUNCTION。接下来我们结合oss c sdk如何使用这两个Callback实现上传数据时从memory或者文件中读取数据并且上传到OSS,以及将存储在OSS上的数据下载到memory或者文件中,相信一起分析完这些,用户对于如何使用oss c sdk设置这两个Callback会有一定的感觉。今天分享一下如何通过oss c sdk使用CURL提供的上传Callback,实现用户对数据进行处理的需求。


上传数据常见的方式有两种:从memory读取、从文件读取,我们一起分析这两种情况下oss c sdk如何利用Callback实现上传的。
首先,我们一起熟悉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);


看完上面的数据结构,用户可能已经有些想法了,接下来我们一起结合具体的上传方式详细说明:
(1)从文件读取数据
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了。具体一些其他细节大家可以看一下源码,有问题也欢迎大家反馈。


(2)从memory读取数据
oss c sdk提供了oss_put_object_from_buffer接口用于从内存读取数据上传到OSS。有了上面的从文件读取数据实现,相应大家也能想到如何实现从内存读取数据了,这个地方就不啰嗦了,简单说一下注意的地方:
aos_http_request_t *aos_http_request_create(aos_pool_t *p)
{
    aos_http_request_t *req;

    req = (aos_http_request_t *)aos_pcalloc(p, sizeof(aos_http_request_t));
    req->port = 80;
    req->method = HTTP_GET;
    req->headers = aos_table_make(p, 5);
    req->query_params = aos_table_make(p, 3);
    aos_list_init(&req->body);
    req->type = BODY_IN_MEMORY;
    req->body_len = 0;
    req->pool = p;
    req->read_body = aos_read_http_body_memory;

    return req;
}


这个地方是 aos_http_request_t(也就是aos_http_request_s的typedef)初始化的地方,默认实现了从memory读取数据,所以oss_put_object_from_buffer函数中的oss_write_request_body_from_buffer实现也比较简单,直接使用了 aos_http_request_t初始化实现。


好了,上面一起看了一下oss c sdk如何使用CURL提供的Callback实现上传数据的一些细节,明天我们会一起分享如何使用CURL提供的Callback实现下载数据的一些细节,感兴趣的同学可以提前看一下oss c sdk中的具体实现。当然, oss c sdk还有待提高,欢迎大家提出宝贵的意见,后续我们也会开源到github,方便大家使用OSS。

展开
收起
yjseu 2015-10-29 09:43:31 13258 0
2 条回答
写回答
取消 提交回答
  • Reoss c sdk利用CURL提供的Callback实现上传
    大哥有没有c的回调设置案例啊
    2016-12-23 17:42:57
    赞同 展开评论 打赏
  • Reoss c sdk利用CURL提供的Callback实现上传
    2016-03-01 20:30:32
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
一个跨平台的云服务SDK需要什么 立即下载
云存储之OSS实战进阶分享 立即下载
OSS运维进阶实战手册 立即下载