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

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

于是改用libcur来做。

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

 ./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

然后编译

 make && make install

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

重点代码是DownloadFile和UploadFile

 #ifndef __MY_HTTP_CURL_H
#define __MY_HTTP_CURL_H #include <string> typedef long long LongSize; typedef int (*pCallBack)(double dtotal, double dnow); class CMYHttpClient
{
public:
CMYHttpClient();
~CMYHttpClient(); public:
/**
* @brief 下载请求, 支持断点续传
* @param strUrl 输入参数,请求的Url地址,如:http://www.baidu.com
* @param strFile 输入参数,本地存储的文件名
* @param timeout 输入参数,超时限制,0为永久等待
* @return 返回是否下载成功:true成功,false失败
*/
bool DownloadFile(const char *strUrl, const char *strFile, pCallBack cb = NULL, int timeout = );
/**
* @brief 获取将要下载的文件的大小,失败返回-1,成功返回非负
* @param strUrl 输入参数,请求的Url地址,如:http://www.baidu.com
* @return 返回文件的大小,失败返回-1
*/
LongSize GetDownloadFileSize(const char *strUrl);
/**
* @brief 上载请求, 支持断点续传
* @param strUrl 输入参数,请求的Url地址,如:http://www.baidu.com
* @param strFile 输入参数,请求上载的文件名
* @param timeout 输入参数,超时限制,0为永久等待
* @return 返回是否下载成功:true成功,false失败
*/
bool UploadFile(const char *strUrl, const char *strFile, pCallBack cb = NULL, int timeout = ); public:
/**
* @brief HTTP POST请求
* @param strUrl 输入参数,请求的Url地址,如:http://www.baidu.com
* @param strPost 输入参数,使用如下格式para1=val1¶2=val2&…
* @param strResponse 输出参数,返回的内容
* @param nResponse 输入输出参数,输入缓冲区大小,返回读入缓冲区的内容大小
* @param strFile 输入文件参数,返回的内容保存在这个文件中
* @param strHeader 输入参数,需要额外指定的http头,如果输入为NULL,则忽略
* @return 返回是否Post成功:0成功,非0失败
*/
int Post(const char *strUrl, const char* strPost, size_t nPost,
const char *strFile, const char* strHeader);
int Post(const char *strUrl, const char* strPost, size_t nPost,
char *strResponse, size_t &nResponse, const char *strHeader);
int Post(const std::string &strUrl, const std::string &strPost,
const char *strFile, const char* strHeader);
int Post(const std::string &strUrl, const std::string &strPost,
std::string &strResponse, const char *strHeader); /**
* @brief HTTP GET请求
* @param strUrl 输入参数,请求的Url地址,如:http://www.baidu.com
* @param strFile 输入文件参数,返回的内容保存在这个文件中
* @param strResponse 输出参数,返回的内容
* @param nResponse 输入输出参数,输入缓冲区大小,返回读入缓冲区的内容大小
* @return 返回是否Get成功:0成功,非0失败
*/
int Get(const char *strUrl, const char *strFile);
int Get(const char *strUrl, std::string &strResponse);
int Get(const char *strUrl, char *strResponse, size_t &nResponse);
int Get(const std::string &strUrl, char *strResponse, size_t &nResponse);
int Get(const std::string &strUrl, std::string &strResponse); /**
* @brief HTTPS POST请求,无证书版本
* @param strUrl 输入参数,请求的Url地址,如:https://www.alipay.com
* @param strPost 输入参数,使用如下格式para1=val1¶2=val2&…
* @param strResponse 输出参数,返回的内容
* @param strHeader 输入参数,需要额外指定的http头,如果输入为NULL,则忽略
* @param pCaPath 输入参数,为CA证书的路径.如果输入为NULL,则不验证服务器端证书的有效性.
* @return 返回是否Post成功:0成功,非0失败
*/
int Posts(const char *strUrl, const char *strPost, size_t nPost,
const char *strFile, const char *strHeader, const char *pCaPath);
int Posts(const std::string &strUrl, const std::string &strPost,
const char *strFile, const char *strHeader, const char *pCaPath);
int Posts(const char *strUrl, const char *strPost, size_t nPost,
char *strResponse, size_t &nResponse, const char *strHeader,
const char *pCaPath);
int Posts(const std::string &strUrl, const std::string &strPost,
std::string &strResponse, const char *strHeader, const char *pCaPath); /**
* @brief HTTPS GET请求,无证书版本
* @param strUrl 输入参数,请求的Url地址,如:https://www.alipay.com
* @param strResponse 输出参数,返回的内容
* @param pCaPath 输入参数,为CA证书的路径.如果输入为NULL,则不验证服务器端证书的有效性.
* @return 返回是否Post成功
*/
int Gets(const std::string &strUrl, std::string &strResponse,
const char *pCaPath = NULL); public:
void SetDebug(bool bDebug);
void AbortOperation(bool bAbort = true) { m_bAbort = bAbort; } private:
bool m_bDebug; //是否打开debug
bool m_bAbort; //是否放弃操作 std::string m_strFile; //需要下载的文件或者上传的文件 pCallBack m_fCB; //上传或者下载时的进度回调函数
LongSize m_lUploadPos; //上传文件的进度 static int OnProgress(void *pClient, curl_off_t dltotal, curl_off_t dlnow,
curl_off_t ultotal, curl_off_t ulnow);
static size_t OnWriteBuffer2File(char* buffer, size_t size, size_t nmemb, void* arg);
static size_t OnReadFile2Buffer(char *buffer, size_t size, size_t nmemb, void* arg);
}; #endif

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

 #include "curl/curl.h"
#include <string>
#include <fstream>
#include <iostream>
#include <sstream> #include "HttpClient.h" using namespace std; CMYHttpClient::CMYHttpClient() :
#ifdef _DEBUG
m_bDebug(true),
#else
m_bDebug(false),
#endif
m_bAbort(false),
m_fCB(NULL),
m_lUploadPos()
{ } CMYHttpClient::~CMYHttpClient()
{ } static int OnDebug(CURL *, curl_infotype itype, char *pData, size_t size, void *)
{
if(itype == CURLINFO_TEXT)
{
//printf("[TEXT]%s\n", pData);
}
else if(itype == CURLINFO_HEADER_IN)
{
printf("[HEADER_IN]%s\n", pData);
}
else if(itype == CURLINFO_HEADER_OUT)
{
printf("[HEADER_OUT]%s\n", pData);
}
else if(itype == CURLINFO_DATA_IN)
{
printf("[DATA_IN]%s\n", pData);
}
else if(itype == CURLINFO_DATA_OUT)
{
printf("[DATA_OUT]%s\n", pData);
} return ;
} int CRGHttpClient::OnProgress(void *pClient, curl_off_t dltotal, curl_off_t dlnow,
curl_off_t ultotal, curl_off_t ulnow)
{
CMYHttpClient* pThis = (CMYHttpClient *)pClient;
if(NULL == pThis || pThis->m_bAbort)
{
//Returning a non-zero value from this callback will cause libcurl to abort
//the transfer and return CURLE_ABORTED_BY_CALLBACK.
return __LINE__;
}
else
{
if(pThis->m_fCB)
{
pThis->m_fCB((double)dltotal, (double)dlnow);
}
#ifdef _DEBUG
if(dltotal)
{
cout << "total bytes expects to download: " << dltotal
<< " and downloaded: " << dlnow << "\n";
}
else if(ultotal)
{
cout << "total bytes expects to upload: " << ultotal
<< " and uploaded: " << ulnow << "\n";
}
#endif return ;
}
} size_t CMYHttpClient::OnWriteBuffer2File(char* buffer, size_t size, size_t nmemb, void* arg)
{
CMYHttpClient* pThis = (CMYHttpClient *)arg;
if(NULL == pThis || pThis->m_bAbort ||
NULL == buffer)
{
return ;
} const char* strFile = pThis->m_strFile.c_str(); ofstream outfile(strFile, ofstream::binary | ofstream::app);
if(outfile.good())
{
const char* pData = (const char *)buffer;
outfile.write(pData, size * nmemb); return nmemb;
} return ;
} size_t CMYHttpClient::OnReadFile2Buffer(char *buffer, size_t size, size_t nmemb, void* arg)
{
CMYHttpClient* pThis = (CMYHttpClient *)arg;
if(NULL == pThis || NULL == buffer)
{
return ;
} ifstream infile(pThis->m_strFile.c_str(), ifstream::binary);
if(infile.good())
{
infile.seekg(pThis->m_lUploadPos, infile.beg);
if(infile.eof() == false)
{
infile.read(buffer, size * nmemb);
pThis->m_lUploadPos += infile.gcount();
return infile.gcount();
}
} return ;
} LongSize CMYHttpClient::GetDownloadFileSize(const char* strUrl)
{
if(NULL == strUrl)
return -; CURL* curl = curl_easy_init();
if(NULL == curl)
return -; curl_easy_setopt(curl, CURLOPT_URL, strUrl);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, );
curl_easy_setopt(curl, CURLOPT_NOBODY, );
CURLcode res = curl_easy_perform(curl);
if(res == CURLE_OK) {
double sz = ;
res = curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &sz); curl_easy_cleanup(curl); return (LongSize)sz;
}
else
{
cout << curl_easy_strerror(res) << endl;
} curl_easy_cleanup(curl); return -;
} bool CMYHttpClient::DownloadFile(const char* strUrl, const char* strFile, pCallBack cb, int timeout)
{
if(NULL == strUrl || NULL == strFile)
{
return false;
} //初始化curl库句柄
CURL* curl = curl_easy_init();
if(NULL == curl)
{
return false;
} m_strFile = string(strFile) + ".dl";
m_fCB = cb;
//支持断点续传,先获取文件大小,如果文件存在并且非空,则断点续传
ifstream infile(m_strFile.c_str(), ifstream::binary);
if(infile.good())
{
infile.seekg(, infile.end);
int length = infile.tellg();
infile.seekg(, infile.beg);
if(length > )
{
stringstream ss;
ss << length;
ss << "-";
LongSize ltotal = GetDownloadFileSize(strUrl);
if(ltotal > )
ss << ltotal;
string srange;
ss >> srange;
curl_easy_setopt(curl, CURLOPT_RANGE, srange.c_str());
}
}
infile.close(); CURLcode res;
if(m_bDebug)
{
curl_easy_setopt(curl, CURLOPT_VERBOSE, );
curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);
} curl_easy_setopt(curl, CURLOPT_URL, strUrl);
curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteBuffer2File);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, this); curl_easy_setopt(curl, CURLOPT_NOPROGRESS, );
curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, OnProgress);
curl_easy_setopt(curl, CURLOPT_XFERINFODATA, this); /**
* 当多个线程都使用超时处理的时候,同时主线程中有sleep或是wait等操作。
* 如果不设置这个选项,libcurl将会发信号打断这个wait从而导致程序退出。
*/
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, );
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, ); //wait for 4 seconds to connect to server
curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout); //0 means block always AbortOperation(false); //reset abort flag
res = curl_easy_perform(curl); curl_easy_cleanup(curl); if(res != CURLE_OK)
{
cout << curl_easy_strerror(res);
}
else
{
#ifdef _WIN32
DeleteFile(strFile);
MoveFile(m_strFile.c_str(), strFile);
#else
unlink(strFile);
rename(m_strFile.c_str(), strFile);
#endif
} m_strFile.clear();
m_fCB = NULL; return res == CURLE_OK;
} bool CMYHttpClient::UploadFile(const char *strUrl, const char *strFile, pCallBack cb, int timeout)
{
if(NULL == strUrl || NULL == strFile)
{
return false;
} //初始化curl库句柄
CURL* curl = curl_easy_init();
if(NULL == curl)
{
return false;
} CURLcode res;
m_fCB = cb;
m_strFile = strFile;
m_lUploadPos = ; curl_easy_setopt(curl, CURLOPT_URL, strUrl);
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); curl_easy_setopt(curl, CURLOPT_READFUNCTION, OnReadFile2Buffer);
curl_easy_setopt(curl, CURLOPT_READDATA, this);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, NULL); curl_easy_setopt(curl, CURLOPT_NOPROGRESS, );
curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, OnProgress);
curl_easy_setopt(curl, CURLOPT_XFERINFODATA, this); curl_easy_setopt(curl, CURLOPT_NOSIGNAL, );
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, ); //wait for 4 seconds to connect to server
curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout); //0 means block always AbortOperation(false); //reset abort flag
res = curl_easy_perform(curl); curl_easy_cleanup(curl); m_strFile.clear();
m_fCB = NULL; if(res != CURLE_OK)
{
cout << curl_easy_strerror(res);
} return res == CURLE_OK;
}

libcurl 下载上传的更多相关文章

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

    一.后台下载/上传 1.简介 使用BackgroundTransferGroup可以十分方便操作上传及下载文件,BackgroundDownloader和BackgroundUploader类中的方法 ...

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

    https 协议下服务器根据网络地址下载上传文件遇到(PKIX:unable to find valid certification path to requested target 的问题) 使用h ...

  3. git下载/上传文件提示:git did not exit cleanly

    问题:git操作下载/上传文件,提示信息如下 TortoiseGit-git did not exit cleanly (exit code 1) TortoiseGit-git did not ex ...

  4. 亚马逊S3下载上传文件

    引用网址: http://www.jxtobo.com/27697.html 下载 CloudBerry Explorer http://www.cloudberrylab.com/download- ...

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

    ftp登陆格式  : ftp://[帐号]:[密码]@[IP]:[端口] ftp://用户名:密码@FTP服务器IP或域名:FTP命令端口/路径/文件名 直接上代码吧,根据需要选择函数,可根据业务自己 ...

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

    原文  http://justwinit.cn/post/7626/ 通常情况下,一般很少使用C语言来直接上传文件,但是遇到使用C语言编程实现文件上传时,该怎么做呢? 借助开源的libcurl库,我们 ...

  7. 一行代码实现Okhttp,Retrofit,Glide下载上传进度监听

    https://mp.weixin.qq.com/s/bopDUFMB7EiK-MhLc3KDXQ essyan 鸿洋 2017-06-29 本文作者 本文由jessyan投稿. jessyan的博客 ...

  8. vc libcurl 模拟上传文件

    http://www.cnblogs.com/killbit/p/5393301.html 附上这篇文章,因为当时就已经想到了模拟上传,但是因为时间关系,所以就直接用PHP写了.现在改进一下,用VC+ ...

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

    在Linux下没有Windows使用360那样去限制某个软件的速度. 但是通过Trickle可以设置某个软件的网速,但是前提是通过Trickle命令连带启动这个软件才可以,不能中途去设置. 比如现在很 ...

随机推荐

  1. 三星 note3销售地查询、销售地代码

    查看销售地代码 用KIES验销售地:记下设定-关于-状态里的序号. 手机不要连接电脑,注意是不要连接,打开KIES3,点工具——固件恢复和初始化,输入大写的型号SM-N900或者SM-N9005,确认 ...

  2. 传智播客课程——Lucene搜索引擎

    Lucene不是一个现成的程序,类似文件搜索程序或web网络爬行器或是一个网站的搜索引擎.Lucene是一个软件库,一个开发工具包,而不是一个具有完整特征的搜索应用程序.它本身只关注文本的索引和搜索. ...

  3. C++中一个函数隐藏的有趣例子

    函数隐藏是一个函数的定义或声明导致其他一些函数不可见. 函数A隐藏函数B的条件:      1. 两个函数具有相同的函数名称      2. 具有不同的作用域.所谓定义域函数定义或声明的位置,如全局作 ...

  4. 今日推荐(三)AndroidResideMenu类似QQ侧滑效果

    效果图: DEMO 本代码即是DEMO,您可以下载后选择您喜欢的IDE运行.SDK版本建议使用4.0以上 Version Migration 从 v1.0, v1.1, v1.2, v1.3 升级到  ...

  5. .net验证控件

    一.客户端验证(用户体验,减少服务器端压力) 二.服务器端验证(防止恶意攻击,客户端js很容易被绕过) 验证控件:RequiredFieldValidator:字段必填:RangeValidator: ...

  6. frontpage 正则 查找与替换

    frontpage正则查找替换 frontpage查找用{}[不是() ]来匹配pattern, 并获取这一匹配 替换时匹配的字符用\1 \2 \3表示 第 N 个标记表达式 \N 在“替换”表达式中 ...

  7. ACM比赛技巧

    一.语言是最重要的基本功   无论侧重于什么方面,只要是通过计算机程序去最终实现的竞赛,语言都是大家要过的第一道关.亚洲赛区的比赛支持的语言包括C/C++与JAVA.笔者首先说说JAVA,众所周知,作 ...

  8. The requested URL ***** was not found on this serve

    Wamp的Alias具体是干什么用的,后面要研究一下!!!! 我是之前创建了一个站点用Alias,后来把站点文件移到了www下后,除了首页都访问不了了.显示“The requested URL *** ...

  9. HTML5 离线缓存详解(转)

    离线缓存是html5新特性之一,简单理解就是第一次加载后将数据缓存,在没有清除缓存前提下,下一次没有网络也可以加载,用在静态数据的网页或游戏比较好用.当然,Html5新的特性都不是所有浏览器都能支持的 ...

  10. 【转】 iOS Provisioning Profile(Certificate)与Code Signing详解

    原文:http://blog.csdn.net/phunxm/article/details/42685597 引言 关于开发证书配置(Certificates & Identifiers & ...