libCurl的文件上傳
最近在需要使用curl的上傳功能,使用libCurl來實現。因此,先使用curl命令操作,然后再使用libCurl實現。
基于Http協議的文件上傳的標準方法是: 基于POST Form的文件上傳 RFC1867。
這個方法使用非常廣泛,這個RFC規定了FORM上傳文件的標準方法,如下介紹了基于libcurl來開發upload功能。
開發實現過程
1. 使用curl 命令行執行代碼, 2. 跟蹤分析 curl的request和response, 3.使用libCurl的API進行開發實現
0. 搭建 upload server
--- 這個請google一些WebServer的搭建,已經參考RFC1867 或網上例子選擇任意一種語言,編寫網絡后太處理代碼。
我使用python的django framework編寫了一個upload處理頁面,
需要FORM的字段
Title-newFileNameInServer
FILE=@....../abc/
url http://192.168.0.61/due/upload/
1. 使用Curl 上傳文件的命令
curl -F"title=dddd.txt" -F "file=@/home/chenglun/upload/abc" http://192.168.0.61/due/upload/
2. 分析
curl --trace trace.log -F"title=dddd.txt" -F "file=@/home/chenglun/upload/abc" http://192.168.0.61/due/upload/
log:
=> connect....
=> Send header, 298 bytes (0x12a)
POST /due/upload ...... bound.....
<= Recv header, 23 bytes (0x17)
HTTP/1.1 100 Continue..
=> Send data, 249 bytes (0xf9)
bound...
Content-Disposition:form-data; name ....
....
bound...
<= Recv header, 17 bytes (0x11)
HTTP/1.1 200 OK..
..............
從trace中可以知道,只需要building一個form,加入對應的Key=value部分然后使用curl的request即可實現如上傳輸過程。
3. 使用libCurl實現
使用API有: curl_formadd(); curl_formfree 生成 一個from,然后使用 curl_easy_setopt(curl, CURLOPT_HTTPPOST, post);設置curl,然后執行,即可。
curl_formadd()使用參考, libCurl的文檔,文檔有例子的。
代碼上半部:
int main() {
CURL *curl;
CURLcode res;
struct data config;
struct stat file_info;
const char * localfile = "/home/chenglun/upload/abc"";
FILE * fp = fopen(localfile, "rb");
if(!fp) {
return -1;
}
if(fstat(fileno(fp), &file_info) != 0) {
return -1;
}
curl = curl_easy_init();
if(curl) {
struct curl_httppost* post = NULL;
struct curl_httppost* last = NULL;
const char * remoteNewFileKey = "title";
const char * remoteNewFileName = "d.ttt";
curl_formadd(&post, &last, CURLFORM_COPYNAME, remoteNewFileKey, CURLFORM_COPYCONTENTS, remoteNewFileName, CURLFORM_END);
curl_formadd(&post, &last, CURLFORM_COPYNAME, "file", CURLFORM_FILE, localfile, CURLFORM_END);
curl_formadd(&post, &last, CURLFORM_COPYNAME, "submit", CURLFORM_COPYCONTENTS, "send", CURLFORM_END);
curl_easy_setopt(curl, CURLOPT_HTTPPOST, post);
下半部:
curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)file_info.st_size); // upload file size--- Content-Length: size
curl_easy_setopt(curl, CURLOPT_MAX_SEND_SPEED_LARGE, 20*1000); // speed limit
// verbal -- for debug
// curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
// curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, my_trace);
// curl_easy_setopt(curl, CURLOPT_DEBUGDATA, &config);
// progress callback
//curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
//curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, cbProgress);
res = curl_easy_perform(curl);
if(res != 0){
ERROR("err string %s", curl_easy_strerror(res));
}
curl_easy_cleanup(curl);
}
fclose(fp);
return 0;
}