C++ libcurl开源库用法

近期在开发一个小项目时候需要用到发送HTTP的请求,这个用Python很容易实现,不过这次代码环境是C++,所以就想用C++写一个发送HTTP请求的代码。

需求:需要在一个Post请求中,发送到HTTP服务端几个参数,同时要发送一批图片。

在一番调研之后发现用libcurl库可以实现需求,但是在写代码的过程中遇到了一些对curl_formadd API理解的问题,特此写出来以供分享。

附上libcurl API的官网:https://curl.haxx.se/libcurl/c/curl_formadd.html

libcurl的主要用法主要包括以下三点:

1、curl全局初始化

CURLcode code = curl_global_init(CURL_GLOBAL_ALL);

2、curl easy初始化

CURL* easy_handler = curl_easy_init();

3、curl 属性的设置

【以下的例子表示的是设置要发送的URL地址】

curl_easy_setopt(easy_handler,CURLOPT_URL,"http://127.0.0.1:8090/detection");

【以下的例子表示的是设置要发送参数,key=“AI_ID”,value="12"】

curl_httppost* post = NULL;
curl_httppost* last = NULL;

使用该方法需要设置两个指针,分别是起始和结束指针。

curl_formadd(&post,&last,CURLFORM_COPYNAME,"AI_ID",CURLFORM_COPYCONTENTS,"12",CURLFORM_END);

4、设置发送方法post

curl_easy_setopt(easy_handler, CURLOPT_HTTPPOST, post);

此处的post是在 curl_formadd中的第一个参数。是一个curl_httppost*

5、执行发送

code = curl_easy_perform(easy_handler);

6、资源释放

curl_formfree(post);  【用来释放curl_formadd添加的数据】
curl_easy_cleanup(easy_handler); 【用来释放easy 句柄资源】
curl_global_cleanup(); 【用来释放全局资源】

==============================================================================================

 但是,在使用过程中出现了一些错误,对http post的发送域没理解对。

我们先看官网翻译之后的内容:

struct curl_httppost * post = NULL; 
 struct curl_httppost * last = NULL; 
 char namebuffer [] =“名称缓冲区”; 
 long namelength = strlen(namebuffer); 
 char buffer [] =“test buffer”; 
 char htmlbuffer [] =“<HTML> test buffer </ HTML>”; 
 long htmlbufferlength = strlen(htmlbuffer); 
 struct curl_forms forms[3]; 
 char file1 [] =“my-face.jpg”; 
 char file2 [] =“your-face.jpg”; 
 / *将空字符添加到htmlbuffer中,以证明
    包含空字符的缓冲区的传输实际上有效
 * / 
 htmlbuffer [8] ='\ 0'; 
 
 / *添加简单的名称/内容部分* / 
 curl_formadd(&post,&last,
              CURLFORM_COPYCONTENTS,“content”,CURLFORM_END); 
 
 / *添加简单名称/内容/ contenttype部分* / 
 curl_formadd(&post,&last,CURLFORM_COPYNAME,“htmlcode”,
              CURLFORM_COPYCONTENTS,“<HTML> </ HTML>”,
              CURLFORM_CONTENTTYPE,“text / html”,CURLFORM_END); 
 
 / *添加名称/ ptrcontent部分* / 
 curl_formadd(&post,&last,CURLFORM_COPYNAME,“name_for_ptrcontent”,
              CURLFORM_PTRCONTENTS,buffer,CURLFORM_END); 
 
 / *添加ptrname / ptrcontent section * / 
 curl_formadd(&post,&last,CURLFORM_PTRNAME,namebuffer,
              CURLFORM_PTRCONTENTS,buffer,CURLFORM_NAMELENGTH,
              namelength,
 
 / *添加名称/ ptrcontent / contenttype section * / 
 curl_formadd(&post,&last,CURLFORM_COPYNAME,“html_code_with_hole”,
              CURLFORM_PTRCONTENTS,htmlbuffer,
              CURLFORM_CONTENTSLENGTH,htmlbufferlength,
              CURLFORM_CONTENTTYPE,“text / html”,CURLFORM_END); 
 
 / *添加简单文件部分* / 
 curl_formadd(&post,&last,CURLFORM_COPYNAME,“picture”,
              CURLFORM_FILE,“my-face.jpg”,CURLFORM_END); 
 
 / *添加文件/ contenttype部分* / 
 curl_formadd(&post,&last,CURLFORM_COPYNAME,“picture”,
              CURLFORM_FILE,“my-face.jpg”,
              CURLFORM_CONTENTTYPE,“image / jpeg”,CURLFORM_END); 
 
 / *添加两个文件部分* /
 curl_formadd(&post,&last,CURLFORM_COPYNAME,“pictures”,
              CURLFORM_FILE,“my-face.jpg”,
              CURLFORM_FILE,“your-face.jpg”,CURLFORM_END); 
 
 / *使用CURLFORM_ARRAY * / 
 forms [0] .option = CURLFORM_FILE 添加两个文件部分; 
 forms [0] .value = file1; 
 forms [1] .option = CURLFORM_FILE; 
 forms [1] .value = file2; 
 forms [2] .option = CURLFORM_END; 
 
 / *添加缓冲区以上传* / 
 curl_formadd(&post,&last,
              CURLFORM_COPYNAME,“name”,
              CURLFORM_BUFFER,“data”,
              CURLFORM_BUFFERPTR,record,
              CURLFORM_BUFFERLENGTH,record_length,
 
 / *结束标记* / 
 curl_formadd(&post,&last,CURLFORM_COPYNAME,“pictures”,
              CURLFORM_ARRAY,forms,CURLFORM_END)不需要选项; 
 / *将文件内容添加为正常的文本后值* / 
 curl_formadd(&post,&last,CURLFORM_COPYNAME,“filecontent”,
              CURLFORM_FILECONTENT,“。bashrc”,CURLFORM_END); 
 / *设置表单info * / 
 curl_easy_setopt(curl,CURLOPT_HTTPPOST,post);
其中,添加两个文件的用法经测试是不能用的。

当我们如果使用了 curl_easy_setopt的时时候就需要如下所示将所有参数传过去,服务端会根据&自动进行分割,从而获取到所需要的参数值。

curl_easy_setopt(easy_handler,CURLOPT_POSTFIELDS,"ID=1&AI_ID=2&gift_url=123")

但是,如果想使用curl_formadd,则需要明白其关键字的用法,且在设置属性的时候不能混用curl_easy_setopt和curl_formadd,只能选择一个来使用。

具体请见官网,以下只写几个常用的关键字

CURLFORM_COPYNAME:在curl_formadd中,该参数后面跟的字符串是key的名字,CURLFORM_COPYCONTENTS:后面跟的字符串为key的值,可以用这种方式设置多个key。

CURLFORM_COPYNAME:在curl_formadd中,该参数同样跟的是key,不过如果想发送文件,则采用关键CURLFORM_FILE,这样可以表示key所对应的文件,设置多个文件,其key相同,就能发送多个文件了。

以下是本人写的一些例子:代码亲测可用

#include <iostream>
#include <string>
using namespace std;
extern "C" {
#include <curl/curl.h>
}
 
size_t process_data(void* buffer,size_t size,size_t nmemb,void* user_p){
    FILE *fp = (FILE*)user_p;
    size_t return_size = fwrite(buffer,size,nmemb,fp);
    cout<<(char*)buffer<<endl;
}
 
int get(void){
    
    CURLcode return_code;
    return_code = curl_global_init(CURL_GLOBAL_ALL);
    if(return_code != CURLE_OK){
        cerr<<"curl_global_init failed!"<<endl;
        return -1;
    }
 
    //get easyhandle
    CURL* easy_handler = curl_easy_init();
    if(easy_handler == NULL){
        cerr<<"curl_easy_init failed!"<<endl;
        curl_global_cleanup();
        return -1;
    }
 
    FILE* fp = fopen("data.html","ab+");
    //set easy opt
    curl_easy_setopt(easy_handler,CURLOPT_URL,"http://blog.csdn.net/JGood");
    curl_easy_setopt(easy_handler,CURLOPT_WRITEFUNCTION,&process_data);
    curl_easy_setopt(easy_handler,CURLOPT_WRITEDATA,fp);
 
    //exe
    curl_easy_perform(easy_handler);
 
    fclose(fp);
    curl_easy_cleanup(easy_handler);
    curl_global_cleanup();
    return 0;
}
 
size_t read_data(void* buffer,size_t size,size_t nmemb,void* user_p){
    FILE* fp = (FILE *)user_p;
    return fread(buffer,size,nmemb,fp);
}
 
int post(void){
    CURLcode code;
    code = curl_global_init(CURL_GLOBAL_ALL);
    if (code != CURLE_OK){
        cerr<<"curl global init failed!"<<endl;
        return -1;
    }
 
    FILE *fp = fopen("data.html","rb");
    if(NULL == fp){
        cerr<<"fopen failed!"<<endl;
        curl_global_cleanup();
        return -1;
    }
    
    fseek(fp,0,2);
    int file_size = ftell(fp);
    rewind(fp);
 
    //get easy handler
    CURL *easy_handler = curl_easy_init();
    if(easy_handler == NULL){
        cerr<<"curl easy init failed!"<<endl;
        fclose(fp);
        curl_global_cleanup();
        return -1;
    }
    curl_easy_setopt(easy_handler,CURLOPT_URL,"http://localhost:8090/detection");
    curl_easy_setopt(easy_handler,CURLOPT_UPLOAD,1);
    curl_easy_setopt(easy_handler,CURLOPT_READFUNCTION,&read_data);
    curl_easy_setopt(easy_handler,CURLOPT_READDATA,fp);
    curl_easy_setopt(easy_handler,CURLOPT_INFILESIZE_LARGE,file_size);
 
    //
    code = curl_easy_perform(easy_handler);
    if(code == CURLE_OK){
        cout<<"upload success"<<endl;
    }
 
    fclose(fp);
    curl_easy_cleanup(easy_handler);
    curl_global_cleanup();
    return 0;
}
 
int post_arguments(void){
    CURLcode code = curl_global_init(CURL_GLOBAL_ALL);
    CURL* easy_handler = curl_easy_init();
    
    curl_easy_setopt(easy_handler,CURLOPT_URL,"http://localhost:8090/detection");
    curl_easy_setopt(easy_handler,CURLOPT_POSTFIELDS,"ID=1&AI_ID=2&gift_url=123");
    code = curl_easy_perform(easy_handler);
    if(code == CURLE_OK){
        cout<<"post arguments success"<<endl;
    }
    curl_easy_cleanup(easy_handler);
    curl_global_cleanup();
    return 0;
}
 
int post_multi_part(void){
    
    CURLcode code;
    code = curl_global_init(CURL_GLOBAL_ALL);
    if(code != CURLE_OK){
        cerr<<"curl global init failed!"<<endl;
        curl_global_cleanup();
        return -1;
    }
    CURL* easy_handler = curl_easy_init();
    if(easy_handler == NULL){
        cerr<<"curl easy init failed!"<<endl;
        curl_global_cleanup();
        return -1;
    }
    curl_easy_setopt(easy_handler,CURLOPT_URL,"http://localhost:8090/detection");
    //curl_easy_setopt(easy_handler,CURLOPT_POSTFIELDS,"ID=1&AI_ID=2&gift_url=123");
    curl_httppost* post = NULL;
    curl_httppost* last = NULL;
 
    string ID = "123";
    string AI_ID = "1234567";
    string gift_url = "sdfsdfdsfdsf";
    curl_formadd(&post,&last,CURLFORM_COPYNAME,"AI_ID",CURLFORM_COPYCONTENTS,AI_ID.c_str(),CURLFORM_END);
    curl_formadd(&post,&last,CURLFORM_COPYNAME,"ID",CURLFORM_COPYCONTENTS,ID.c_str(),CURLFORM_END);
    curl_formadd(&post,&last,CURLFORM_COPYNAME,"gift_url",CURLFORM_COPYCONTENTS,gift_url.c_str(),CURLFORM_END);
    curl_formadd(&post,&last,CURLFORM_COPYNAME,"newImg",CURLFORM_FILE,"./picture_1.png",CURLFORM_END);
    curl_formadd(&post,&last,CURLFORM_COPYNAME,"newImg",CURLFORM_FILE,"./picture_2.png",CURLFORM_END);
    curl_formadd(&post,&last,CURLFORM_COPYNAME,"newImg",CURLFORM_FILE,"./picture_3.png",CURLFORM_END);
   
 
    char buffer[1024];
    snprintf(buffer,sizeof(buffer),"%d",123);
    cout<<buffer<<endl;
 
   /*
    char file1[] = "./picture_1.png";
    char file2[] = "./picture_2.png";
    struct curl_forms arr[3];
    arr[0].option = CURLFORM_FILE;
    arr[0].value = file1;
    arr[1].option = CURLFORM_FILE;
    arr[1].value = file2;
    arr[2].option = CURLFORM_END;
    curl_formadd(&post,&last,CURLFORM_COPYNAME,"newImg",CURLFORM_ARRAY,arr,CURLFORM_END);
*/
    curl_easy_setopt(easy_handler,CURLOPT_HTTPPOST,post);
    code = curl_easy_perform(easy_handler);
    if(code != CURLE_OK){
        cerr<<"curl easy perform failed!"<<endl;
        curl_easy_cleanup(easy_handler);
        curl_global_cleanup();
        return -1;
    }
    curl_formfree(post);
    curl_easy_cleanup(easy_handler);
    curl_global_cleanup();
    return 0;
}
 
 
int main(void){
    //get();
    //post_arguments();
    post_multi_part();
    return 0;
}
                        
原文链接:https://blog.csdn.net/apacat/article/details/98956075

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值