使用osscsdk自定義上傳和下載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
“, 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、下載資料
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
“, 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);
…
}
相關文章
- mac下iterm2使用rz和sz上傳下載Mac
- 檔案上傳和下載功能
- JAVA中使用FTPClient上傳下載JavaFTPclient
- 使用SecureCRT上傳下載檔案Securecrt
- Dynamics CRM中自定義頁面實現附件管理包含下載模板、上傳、下載、刪除
- Vue + Element 自定義上傳封面元件Vue元件
- 【SVN】Eclipse中使用Svn上傳和下載程式碼Eclipse
- vsftpd匿名使用者上傳和下載的配置FTP
- 使用Thread打造上傳下載器thread
- Typora中自定義命令上傳圖片
- 自定義上傳圖片拼圖遊戲遊戲
- Docker自定義映象上傳阿里雲Docker阿里
- 用SecureCRT來上傳和下載資料Securecrt
- xshell 使用 sftp上傳下載檔案FTP
- ftp上傳工具下載,ftp上傳工具下載使用教程,Linux如何配置ftp伺服器?FTPLinux伺服器
- iTerm2下配置ssh自動登入和使用lrzsz上傳下載
- 檔案上傳下載
- 如何在命令列中使用 ftp 命令上傳和下載檔案命令列FTP
- 自定義檔案上傳功能實現方法
- 在.NET 6.0上使用Kestrel配置和自定義HTTPSHTTP
- AntD框架的upload元件上傳圖片時使用customRequest方法自定義上傳行為框架元件
- Ant-Design-Vue 自定義上傳和圖片預覽功能Vue
- 前端實現檔案下載和拖拽上傳前端
- SpringMVC中的檔案上傳和下載SpringMVC
- 面試題:上傳和下載怎麼測試?面試題
- Java Struts檔案上傳和下載詳解Java
- 基於servlet的檔案上傳和下載Servlet
- SecureCRT上傳下載檔案教程(Zmodem使用教程)Securecrt
- 檔案上傳與下載
- JAVA檔案上傳下載Java
- Vertx 檔案上傳下載
- centos上傳下載檔案CentOS
- iOS-OC-AFNetworking上傳和下載(回撥下載進度)iOS
- springboot 中檔案的上傳和下載Spring Boot
- linux安裝rz和sz上傳下載命令Linux
- 使用 canvas 繪製圖片,然後下載、上傳Canvas
- MySQL使用之五_自定義函式和自定義過程MySql函式
- element-ui 上傳元件 自定義上傳沒有進度條解決方法UI元件