前面分享了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。
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。