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\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 = (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 }
时间: 2024-10-20 06:25:25

libcurl 下载上传的相关文章

WP8.1 Study17:网络之后台下载/上传及HttpClient

一.后台下载/上传 1.简介 使用BackgroundTransferGroup可以十分方便操作上传及下载文件,BackgroundDownloader和BackgroundUploader类中的方法提供一系列方法交互这一过程,因此我们也可以利用live tile或toast显示传输的状态. 2.下载代码 代码一: async void DownloadFile(Uri sourceUri, string destFilename) { cts = new CancellationTokenSo

https 协议下服务器根据网络地址下载上传文件问题

https 协议下服务器根据网络地址下载上传文件遇到(PKIX:unable to find valid certification path to requested target 的问题) 使用httpclient  所有站点全部信任 不做身份鉴定: 1 public static CloseableHttpClient getHttpClient() throws Exception { 2 SSLConnectionSocketFactory sslsf = null; 3 Poolin

shell 模式下tftp下载上传文件的命令

tftp下载文件: tftp -pl test.app 6.6.6.6 test.app是要下载的文件: 6.6.6.6是下载所通过的网卡: tftp上传文件: tftp -gr test.app 6.6.6.6 test.app是要上传到设备的文件: 6.6.6.6是上传通过的网卡:

Ubuntu 16.04通过Trickle限制某个软件的下载/上传速度

在Linux下没有Windows使用360那样去限制某个软件的速度. 但是通过Trickle可以设置某个软件的网速,但是前提是通过Trickle命令连带启动这个软件才可以,不能中途去设置. 比如现在很多视频网站都实现了P2P,所以可以在看某个视频时通过Trickle命令启动浏览器来实现限速. 1.安装: sudo apt-get install trickle 2.命令格式 trickle -d download-bandwidth -u upload-bandwidth command 3.命

JAVA从局域网共享文件夹中下载上传文件以及java访问共享文件夹

1 package com.xx.test; 2 3 4 import java.io.BufferedInputStream; 5 import java.io.BufferedOutputStream; 6 import java.io.File; 7 import java.io.FileInputStream; 8 import java.io.FileOutputStream; 9 import java.io.IOException; 10 import java.io.InputS

电信说的几兆带宽和自己看到的下载/上传速度有什么关系

李老板开了家小网吧,在电信办了4M的电信宽带(ADSL接入),但是他回到家里用IE浏览器测试下载速度却只有400KB/S左右,而且不太稳定,给其他人传送文件速度只有50多KB/S.但是他问他的朋友张老板的4M电信宽带(光纤接入)下载和给其它人传文件速度有多少时,张老板却说,下载有450KB/S左右,很稳定,快的时候有500KB/S,给其它人发送文件的速度也有450~500多KB/S. 于是这个李老板很火,认为电信欺骗了他,说是4M宽带,下载只有400KB/S,而且发送文件(上传)只有50多KB/

vc libcurl 模拟上传文件

http://www.cnblogs.com/killbit/p/5393301.html 附上这篇文章,因为当时就已经想到了模拟上传,但是因为时间关系,所以就直接用PHP写了.现在改进一下,用VC+libcurl库.   我们也直接可以用MYSQL写入这段上传代码就可以了. select 0x3C3F70687020696628245F46494C45535B2766696C65275D5B276E616D65275D20213D20222229207B20636F70792028245F46

C#FTP操作类含下载上传删除获取目录文件及子目录列表等等

ftp登陆格式  : ftp://[帐号]:[密码]@[IP]:[端口] ftp://用户名:密码@FTP服务器IP或域名:FTP命令端口/路径/文件名 直接上代码吧,根据需要选择函数,可根据业务自己修改,如日志记录,提示等等 using System; using System.Collections.Generic; using System.Text; using System.IO; using System.Net; using System.Windows.Forms; using

C语言 HTTP上传文件-利用libcurl库上传文件

原文  http://justwinit.cn/post/7626/ 通常情况下,一般很少使用C语言来直接上传文件,但是遇到使用C语言编程实现文件上传时,该怎么做呢? 借助开源的libcurl库,我们可以容易地实现这个功能.Libcurl是一个免费易用的客户端URL传输库,主要功能是用不同的协议连接和沟通不同的服务器,libcurl当前支持DICT, FILE, FTP, FTPS, Gopher, HTTP, HTTPS, IMAP,IMAPS, LDAP, LDAPS, POP3, POP3