zoukankan      html  css  js  c++  java
  • libcurl 下载上传

    近来一个新的项目需要使用到http。

    本来用socket来写一个的,后来发现功能实在太简单,有点捉襟见肘。

    于是改用libcur来做。

    首先下载libcur的源码,然后配置:

    1 ./configure --prefix=$HOME/csource/linux/ CFLAGS='-O2 -m32 -fPIC' --enable-optimize  --enable-static=libcurl.a --enable-ftp --without-zlib --disable-gopher --disable-rtsp --disable-dict --enable-proxy --disable-telnet  --enable-tftp   --disable-pop3   --disable-imap   --enable-smtp  --enable-ipv6  --enable-http -enable-crypto-auth  --without-gnutls --without-nss --without-ca-bundle --with-random=/dev/urandom

    然后编译

    1 make && make install

    代码如下,使用一个c++类来管理

    重点代码是DownloadFile和UploadFile

      1 #ifndef __MY_HTTP_CURL_H
      2 #define __MY_HTTP_CURL_H
      3 
      4 #include <string>
      5 
      6 typedef long long LongSize;
      7 
      8 typedef int (*pCallBack)(double dtotal, double dnow);
      9 
     10 class CMYHttpClient
     11 {
     12 public:
     13         CMYHttpClient();
     14         ~CMYHttpClient();
     15 
     16 public:
     17         /**
     18         * @brief 下载请求, 支持断点续传
     19         * @param strUrl 输入参数,请求的Url地址,如:http://www.baidu.com
     20         * @param strFile 输入参数,本地存储的文件名
     21         * @param timeout 输入参数,超时限制,0为永久等待
     22         * @return 返回是否下载成功:true成功,false失败
     23         */
     24         bool DownloadFile(const char *strUrl, const char *strFile, pCallBack cb = NULL, int timeout = 0);
     25         /**
     26         * @brief 获取将要下载的文件的大小,失败返回-1,成功返回非负
     27         * @param strUrl 输入参数,请求的Url地址,如:http://www.baidu.com
     28         * @return 返回文件的大小,失败返回-1
     29         */
     30         LongSize GetDownloadFileSize(const char *strUrl);
     31         /**
     32         * @brief 上载请求, 支持断点续传
     33         * @param strUrl 输入参数,请求的Url地址,如:http://www.baidu.com
     34         * @param strFile 输入参数,请求上载的文件名
     35         * @param timeout 输入参数,超时限制,0为永久等待
     36         * @return 返回是否下载成功:true成功,false失败
     37         */
     38         bool UploadFile(const char *strUrl, const char *strFile, pCallBack cb = NULL, int timeout = 0);
     39 
     40 public:
     41         /**
     42         * @brief HTTP POST请求
     43         * @param strUrl 输入参数,请求的Url地址,如:http://www.baidu.com
     44         * @param strPost 输入参数,使用如下格式para1=val1¶2=val2&…
     45         * @param strResponse 输出参数,返回的内容
     46         * @param nResponse 输入输出参数,输入缓冲区大小,返回读入缓冲区的内容大小
     47         * @param strFile 输入文件参数,返回的内容保存在这个文件中
     48         * @param strHeader 输入参数,需要额外指定的http头,如果输入为NULL,则忽略
     49         * @return 返回是否Post成功:0成功,非0失败
     50         */
     51         int Post(const char *strUrl, const char* strPost, size_t nPost,
     52                         const char *strFile, const char* strHeader);
     53         int Post(const char *strUrl, const char* strPost, size_t nPost,
     54                  char *strResponse, size_t &nResponse, const char *strHeader);
     55         int Post(const std::string &strUrl, const std::string &strPost,
     56                         const char *strFile, const char* strHeader);
     57         int Post(const std::string &strUrl, const std::string &strPost,
     58                 std::string &strResponse, const char *strHeader);
     59 
     60         /**
     61         * @brief HTTP GET请求
     62         * @param strUrl 输入参数,请求的Url地址,如:http://www.baidu.com
     63         * @param strFile 输入文件参数,返回的内容保存在这个文件中
     64         * @param strResponse 输出参数,返回的内容
     65         * @param nResponse 输入输出参数,输入缓冲区大小,返回读入缓冲区的内容大小
     66         * @return 返回是否Get成功:0成功,非0失败
     67         */
     68         int Get(const char *strUrl, const char *strFile);
     69         int Get(const char *strUrl, std::string &strResponse);
     70         int Get(const char *strUrl, char *strResponse, size_t &nResponse);
     71         int Get(const std::string &strUrl, char *strResponse, size_t &nResponse);
     72         int Get(const std::string &strUrl, std::string &strResponse);
     73 
     74         /**
     75         * @brief HTTPS POST请求,无证书版本
     76         * @param strUrl 输入参数,请求的Url地址,如:https://www.alipay.com
     77         * @param strPost 输入参数,使用如下格式para1=val1¶2=val2&…
     78         * @param strResponse 输出参数,返回的内容
     79         * @param strHeader 输入参数,需要额外指定的http头,如果输入为NULL,则忽略
     80         * @param pCaPath 输入参数,为CA证书的路径.如果输入为NULL,则不验证服务器端证书的有效性.
     81         * @return 返回是否Post成功:0成功,非0失败
     82         */
     83         int Posts(const char *strUrl, const char *strPost, size_t nPost,
     84                         const char *strFile, const char *strHeader, const char *pCaPath);
     85         int Posts(const std::string &strUrl, const std::string &strPost,
     86                         const char *strFile, const char *strHeader, const char *pCaPath);
     87         int Posts(const char *strUrl, const char *strPost, size_t nPost,
     88                 char *strResponse, size_t &nResponse, const char *strHeader,
     89                 const char *pCaPath);
     90         int Posts(const std::string &strUrl, const std::string &strPost,
     91                         std::string &strResponse, const char *strHeader, const char *pCaPath);
     92 
     93         /**
     94         * @brief HTTPS GET请求,无证书版本
     95         * @param strUrl 输入参数,请求的Url地址,如:https://www.alipay.com
     96         * @param strResponse 输出参数,返回的内容
     97         * @param pCaPath 输入参数,为CA证书的路径.如果输入为NULL,则不验证服务器端证书的有效性.
     98         * @return 返回是否Post成功
     99         */
    100         int Gets(const std::string &strUrl, std::string &strResponse,
    101                         const char *pCaPath = NULL);
    102 
    103 public:
    104         void SetDebug(bool bDebug);
    105         void AbortOperation(bool bAbort = true) { m_bAbort = bAbort; }
    106 
    107 private:
    108         bool m_bDebug;          //是否打开debug
    109         bool m_bAbort;          //是否放弃操作
    110 
    111         std::string m_strFile;  //需要下载的文件或者上传的文件
    112 
    113         pCallBack       m_fCB;  //上传或者下载时的进度回调函数
    114         LongSize        m_lUploadPos;   //上传文件的进度
    115 
    116         static int OnProgress(void *pClient, curl_off_t dltotal, curl_off_t dlnow,
    117                         curl_off_t ultotal, curl_off_t ulnow);
    118         static size_t OnWriteBuffer2File(char* buffer, size_t size, size_t nmemb, void* arg);
    119         static size_t OnReadFile2Buffer(char *buffer, size_t size, size_t nmemb, void* arg);
    120 };
    121 
    122 #endif

    几个主要方法,其中https的编译需要openssl,所以我没做支持。

      1 #include "curl/curl.h"
      2 #include <string>
      3 #include <fstream>
      4 #include <iostream>
      5 #include <sstream>
      6 
      7 #include "HttpClient.h"
      8 
      9 
     10 using namespace std;
     11 
     12 CMYHttpClient::CMYHttpClient() :
     13 #ifdef _DEBUG
     14         m_bDebug(true),
     15 #else
     16         m_bDebug(false),
     17 #endif
     18         m_bAbort(false),
     19         m_fCB(NULL),
     20         m_lUploadPos(0)
     21 {
     22 
     23 }
     24 
     25 CMYHttpClient::~CMYHttpClient()
     26 {
     27 
     28 }
     29 
     30 static int OnDebug(CURL *, curl_infotype itype, char *pData, size_t size, void *)
     31 {
     32         if(itype == CURLINFO_TEXT)
     33         {
     34                 //printf("[TEXT]%s
    ", pData);
     35         }
     36         else if(itype == CURLINFO_HEADER_IN)
     37         {
     38                 printf("[HEADER_IN]%s
    ", pData);
     39         }
     40         else if(itype == CURLINFO_HEADER_OUT)
     41         {
     42                 printf("[HEADER_OUT]%s
    ", pData);
     43         }
     44         else if(itype == CURLINFO_DATA_IN)
     45         {
     46                 printf("[DATA_IN]%s
    ", pData);
     47         }
     48         else if(itype == CURLINFO_DATA_OUT)
     49         {
     50                 printf("[DATA_OUT]%s
    ", pData);
     51         }
     52 
     53         return 0;
     54 }
     55 
     56 int CRGHttpClient::OnProgress(void *pClient, curl_off_t dltotal, curl_off_t dlnow,
     57                 curl_off_t ultotal, curl_off_t ulnow)
     58 {
     59         CMYHttpClient* pThis = (CMYHttpClient *)pClient;
     60         if(NULL == pThis || pThis->m_bAbort)
     61         {
     62                 //Returning a non-zero value from this callback will cause libcurl to abort
     63                 //the transfer and return CURLE_ABORTED_BY_CALLBACK.
     64                 return __LINE__;
     65         }
     66         else
     67         {
     68                 if(pThis->m_fCB)
     69                 {
     70                         pThis->m_fCB((double)dltotal, (double)dlnow);
     71                 }
     72 #ifdef _DEBUG
     73                 if(dltotal)
     74                 {
     75                         cout << "total bytes expects to download: " << dltotal
     76                                 << " and downloaded: " << dlnow << "
    ";
     77                 }
     78                 else if(ultotal)
     79                 {
     80                         cout << "total bytes expects to upload: " << ultotal
     81                                 << " and uploaded: " << ulnow << "
    ";
     82                 }
     83 #endif
     84 
     85                 return 0;
     86         }
     87 }
     88 
     89 size_t CMYHttpClient::OnWriteBuffer2File(char* buffer, size_t size, size_t nmemb, void* arg)
     90 {
     91         CMYHttpClient* pThis = (CMYHttpClient *)arg;
     92         if(NULL == pThis || pThis->m_bAbort ||
     93                         NULL == buffer)
     94         {
     95                 return 0;
     96         }
     97 
     98         const char* strFile = pThis->m_strFile.c_str();
     99 
    100         ofstream outfile(strFile, ofstream::binary | ofstream::app);
    101         if(outfile.good())
    102         {
    103                 const char* pData = (const char *)buffer;
    104                 outfile.write(pData, size * nmemb);
    105 
    106                 return nmemb;
    107         }
    108 
    109         return 0;
    110 }
    111 
    112 size_t CMYHttpClient::OnReadFile2Buffer(char *buffer, size_t size, size_t nmemb, void* arg)
    113 {
    114         CMYHttpClient* pThis = (CMYHttpClient *)arg;
    115         if(NULL == pThis || NULL == buffer)
    116         {
    117                 return 0;
    118         }
    119 
    120         ifstream infile(pThis->m_strFile.c_str(), ifstream::binary);
    121         if(infile.good())
    122         {
    123                 infile.seekg(pThis->m_lUploadPos, infile.beg);
    124                 if(infile.eof() == false)
    125                 {
    126                         infile.read(buffer, size * nmemb);
    127                         pThis->m_lUploadPos += infile.gcount();
    128                         return infile.gcount();
    129                 }
    130         }
    131 
    132         return 0;
    133 }
    134 
    135 LongSize CMYHttpClient::GetDownloadFileSize(const char* strUrl)
    136 {
    137         if(NULL == strUrl)
    138                 return -1;
    139 
    140         CURL* curl = curl_easy_init();
    141         if(NULL == curl)
    142                 return -1;
    143 
    144         curl_easy_setopt(curl, CURLOPT_URL, strUrl);
    145         curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1);
    146         curl_easy_setopt(curl, CURLOPT_NOBODY, 1);
    147         CURLcode res = curl_easy_perform(curl);
    148         if(res == CURLE_OK) {
    149                 double sz = 0;
    150                 res = curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &sz);
    151 
    152                 curl_easy_cleanup(curl);
    153 
    154                 return (LongSize)sz;
    155         }
    156         else
    157         {
    158                 cout << curl_easy_strerror(res) << endl;
    159         }
    160 
    161         curl_easy_cleanup(curl);
    162 
    163         return -1;
    164 }
    165 
    166 bool CMYHttpClient::DownloadFile(const char* strUrl, const char* strFile, pCallBack cb, int timeout)
    167 {
    168         if(NULL == strUrl || NULL == strFile)
    169         {
    170                 return false;
    171         }
    172 
    173         //初始化curl库句柄
    174         CURL* curl = curl_easy_init();
    175         if(NULL == curl)
    176         {
    177                 return false;
    178         }
    179 
    180         m_strFile = string(strFile) + ".dl";
    181         m_fCB = cb;
    182         //支持断点续传,先获取文件大小,如果文件存在并且非空,则断点续传
    183         ifstream infile(m_strFile.c_str(), ifstream::binary);
    184         if(infile.good())
    185         {
    186                 infile.seekg(0, infile.end);
    187                 int length = infile.tellg();
    188                 infile.seekg(0, infile.beg);
    189                 if(length > 0)
    190                 {
    191                         stringstream ss;
    192                         ss << length;
    193                         ss << "-";
    194                         LongSize ltotal = GetDownloadFileSize(strUrl);
    195                         if(ltotal > 0)
    196                                 ss << ltotal;
    197                         string srange;
    198                         ss >> srange;
    199                         curl_easy_setopt(curl, CURLOPT_RANGE, srange.c_str());
    200                 }
    201         }
    202         infile.close();
    203 
    204         CURLcode res;
    205         if(m_bDebug)
    206         {
    207                 curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
    208                 curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);
    209         }
    210 
    211         curl_easy_setopt(curl, CURLOPT_URL, strUrl);
    212         curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
    213         curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteBuffer2File);
    214         curl_easy_setopt(curl, CURLOPT_WRITEDATA, this);
    215 
    216         curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
    217         curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, OnProgress);
    218         curl_easy_setopt(curl, CURLOPT_XFERINFODATA, this);
    219 
    220         /**
    221         * 当多个线程都使用超时处理的时候,同时主线程中有sleep或是wait等操作。
    222         * 如果不设置这个选项,libcurl将会发信号打断这个wait从而导致程序退出。
    223         */
    224         curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
    225         curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 4); //wait for 4 seconds to connect to server
    226         curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout);       //0 means block always
    227 
    228         AbortOperation(false);  //reset abort flag
    229         res = curl_easy_perform(curl);
    230 
    231         curl_easy_cleanup(curl);
    232 
    233         if(res != CURLE_OK)
    234         {
    235                 cout << curl_easy_strerror(res);
    236         }
    237         else
    238         {
    239 #ifdef _WIN32
    240                 DeleteFile(strFile);
    241                 MoveFile(m_strFile.c_str(), strFile);
    242 #else
    243                 unlink(strFile);
    244                 rename(m_strFile.c_str(), strFile);
    245 #endif
    246         }
    247 
    248 
    249         m_strFile.clear();
    250         m_fCB = NULL;
    251 
    252         return res == CURLE_OK;
    253 }
    254 
    255 bool CMYHttpClient::UploadFile(const char *strUrl, const char *strFile, pCallBack cb, int timeout)
    256 {
    257         if(NULL == strUrl || NULL == strFile)
    258         {
    259                 return false;
    260         }
    261 
    262         //初始化curl库句柄
    263         CURL* curl = curl_easy_init();
    264         if(NULL == curl)
    265         {
    266                 return false;
    267         }
    268 
    269         CURLcode res;
    270         m_fCB = cb;
    271         m_strFile = strFile;
    272         m_lUploadPos = 0;
    273 
    274         curl_easy_setopt(curl, CURLOPT_URL, strUrl);
    275         curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
    276 
    277         curl_easy_setopt(curl, CURLOPT_READFUNCTION, OnReadFile2Buffer);
    278         curl_easy_setopt(curl, CURLOPT_READDATA, this);
    279         curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, NULL);
    280 
    281         curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
    282         curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, OnProgress);
    283         curl_easy_setopt(curl, CURLOPT_XFERINFODATA, this);
    284 
    285         curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
    286         curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 4); //wait for 4 seconds to connect to server
    287         curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout);       //0 means block always
    288 
    289         AbortOperation(false);  //reset abort flag
    290         res = curl_easy_perform(curl);
    291 
    292         curl_easy_cleanup(curl);
    293 
    294         m_strFile.clear();
    295         m_fCB = NULL;
    296 
    297         if(res != CURLE_OK)
    298         {
    299                 cout << curl_easy_strerror(res);
    300         }
    301 
    302         return res == CURLE_OK;
    303 }
  • 相关阅读:
    Java 8 Lambda 表达式
    OSGi 系列(十二)之 Http Service
    OSGi 系列(十三)之 Configuration Admin Service
    OSGi 系列(十四)之 Event Admin Service
    OSGi 系列(十六)之 JDBC Service
    OSGi 系列(十)之 Blueprint
    OSGi 系列(七)之服务的监听、跟踪、声明等
    OSGi 系列(六)之服务的使用
    OSGi 系列(三)之 bundle 事件监听
    OSGi 系列(三)之 bundle 详解
  • 原文地址:https://www.cnblogs.com/jojodru/p/3945601.html
Copyright © 2011-2022 走看看