首页 > 代码库 > libcurl 下载上传
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; //是否打开debug109 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\n", pData); 35 } 36 else if(itype == CURLINFO_HEADER_IN) 37 { 38 printf("[HEADER_IN]%s\n", pData); 39 } 40 else if(itype == CURLINFO_HEADER_OUT) 41 { 42 printf("[HEADER_OUT]%s\n", pData); 43 } 44 else if(itype == CURLINFO_DATA_IN) 45 { 46 printf("[DATA_IN]%s\n", pData); 47 } 48 else if(itype == CURLINFO_DATA_OUT) 49 { 50 printf("[DATA_OUT]%s\n", 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 << "\n"; 77 } 78 else if(ultotal) 79 { 80 cout << "total bytes expects to upload: " << ultotal 81 << " and uploaded: " << ulnow << "\n"; 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 = http://www.mamicode.com/(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 else157 {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 server226 curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout); //0 means block always227 228 AbortOperation(false); //reset abort flag229 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 else238 {239 #ifdef _WIN32240 DeleteFile(strFile);241 MoveFile(m_strFile.c_str(), strFile);242 #else243 unlink(strFile);244 rename(m_strFile.c_str(), strFile);245 #endif246 }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 server287 curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout); //0 means block always288 289 AbortOperation(false); //reset abort flag290 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 }
libcurl 下载上传
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。