近来一个新的项目需要使用到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. Storm-1.0.1+ZooKeeper-3.4.8+Netty-4.1.3 HA集群安装

    Storm-1.0.1+ZooKeeper-3.4.8+Netty-4.1.3 HA集群安装 下载Storm-1.0.1 http://mirrors.tuna.tsinghua.edu.cn/apa ...

  2. Ring - HDU 2296(自动机+dp)

    题目大意:斯蒂文想送给他女盆友一个戒指,并且他想在戒指上刻一些字,他非常了解他女盆友喜欢什么单词,比如"love""forvevr"....并且他还把女盆友喜欢 ...

  3. Java学习的随笔(2)Java语言的三大特性

    1.面向对象的三大特性 面向对象的三大特性主要包括:继承.封装.多态 (1)继承:就是指子类(导出类)获得了基类的全部功能(所有的域和方法).  注:在子类中,想要调用基类的方法可以使用“super. ...

  4. Unity3D 画线插件 Vectrosity_Simple2DLine

    Vectrosity是一个很方便的画线插件,用它我们可以画出2D,3D,贝塞尔,圆,椭圆等各种线条图案. :链接: http://pan.baidu.com/s/1pJjTFjt 密码: uesn 首 ...

  5. Android 图片选择器

    图片选择器,遍历系统所有图片并显示,点击查看大图,长按选中,并将结果返回 字体颜色res/color建立text_selecor.xml <selector xmlns:android=&quo ...

  6. POJ2250:Compromise(LCS)

    Description In a few months the European Currency Union will become a reality. However, to join the ...

  7. iOS 实现时间线列表效果

    之前看到美团的订单详情页面很有特色,于是决定模仿一下这个效果. 其实就是简单的 TableView 技巧,下面我们就来一步一步实现它. 画个泡泡 首先到 Sketch 里画出气泡的效果 很简单,一个圆 ...

  8. Java 8 Lambda表达式10个示例【存】

    PS:不能完全参考文章的代码,请参考这个文件http://files.cnblogs.com/files/AIThink/Test01.zip 在Java 8之前,如果想将行为传入函数,仅有的选择就是 ...

  9. 正则表达式中/i,/g,/m的作用

    一./i (ignorCase)忽略大小写,注意仅是忽略大小写,并不忽略全半角. 二./g (globle)全文查找出现的所有匹配字符 三./m 1.(mutiple)多行查找2.m 影响 ^.$.3 ...

  10. 用CSS3实现带小三角形的div框(不用图片)

    现在看到了很多带小三角形的方框,如微信.Mac版的QQ.QQ空间的时间轴等等,在聊天或者是发表的状态的内容外面都有一个带小三角形的矩形框包围着,感觉看着很不错,于是决定亲自动手写一个,我上次用的是偏移 ...