libcurl的主页:
http://curl.haxx.se/
头文件:
/**********************************************************************
* Copyright (C) 2014 - - All Rights Reserved
*
* 文件名称: Downloader_LibCurl.h
* 摘 要: 下载器 - LibCurl实现
*
* 作 者: yanglinbo,
* 修 改: 查看文件最下方.
*
***********************************************************************/

#ifndef __Downloader_LibCurl_H__
#define
__Downloader_LibCurl_H__


#include
<
curl
/
curl.h
>
#include
<
fstream
>
#include
<
string
>


class
CDownloader
{
public:
CDownloader(void);
virtual ~CDownloader(void);

public:
/// 线程入口函数
virtual bool run();

/// 启动下载
virtual bool start(const std::string& strUrl, const std::string& strLocalFile);

/// 停止下载
virtual bool stop();

/// 是否运行状态
bool isRunning() const;

protected:
/// 写入回调
static size_t handleWrite(void *buffer, size_t size, size_t nmemb, void *userp);

/// 进度回调
static size_t handleProgress(void *buffer, double dltotal, double dlnow, double ultotal, double ulnow);

protected:
/// 写入回调
size_t onWrite(void *buffer, size_t size, size_t nmemb);

/// 进度回调
size_t onProgress(const double& dltotal, const double& dlnow);

/// 下载回调
void onDownload();

protected:
/// 设置libcurl选项
void setOption();

/// 清除数据
void clear();

protected:
CURL* m_pCurl; ///< libcurl句柄
FILE* m_pFile; ///< 文件指针

bool m_bRunning; ///< 运行标志

std::string m_strDownloadUrl; ///< 下载链接
std::string m_strLocalFilePath; ///< 本地文件路径
};


#endif
实现文件:
/**********************************************************************
* Copyright (C) 2014 - - All Rights Reserved
*
* 文件名称: Downloader_LibCurl.cpp
* 摘 要: 下载器 - LibCurl实现
*
* 作 者: yanglinbo,
* 修 改: 查看文件最下方.
*
***********************************************************************/

#include
"
StdAfx.h
"
#include
"
Downloader.h
"


CDownloader::CDownloader(
void
)
: m_pCurl(NULL)
, m_pFile(NULL)
, m_bRunning(
false
)
{
}

CDownloader::
~
CDownloader(
void
)
{
stop();
}

bool
CDownloader::run()
{
onDownload();
return true;
}

bool
CDownloader::isRunning()
const
{
return m_bRunning;
}

void
CDownloader::clear()
{
if (m_pFile)
{
fclose(m_pFile);
m_pFile = NULL;
}

if (m_pCurl)
{
curl_easy_cleanup(m_pCurl);
m_pCurl = NULL;
curl_global_cleanup();
}

m_strDownloadUrl.clear();
m_strLocalFilePath.clear();
}

void
CDownloader::setOption()
{
// 远程URL,支持 http, https, ftp
curl_easy_setopt(m_pCurl, CURLOPT_URL, m_strDownloadUrl.c_str());

// 设置User-Agent
std::string useragent = _T("Mozilla/5.0 (Windows NT 6.1; WOW64; rv:13.0) Gecko/20100101 Firefox/13.0.1");
curl_easy_setopt(m_pCurl, CURLOPT_USERAGENT, useragent.c_str());

// 设置重定向的最大次数
curl_easy_setopt(m_pCurl, CURLOPT_MAXREDIRS, 5);

// 设置301、302跳转跟随location
curl_easy_setopt(m_pCurl, CURLOPT_FOLLOWLOCATION, 1);

curl_easy_setopt(m_pCurl, CURLOPT_NOSIGNAL, 1L);
curl_easy_setopt(m_pCurl, CURLOPT_POST, false);

// 下载内容回调函数
curl_easy_setopt(m_pCurl, CURLOPT_WRITEFUNCTION, handleWrite);
curl_easy_setopt(m_pCurl, CURLOPT_WRITEDATA, this);

// 进度回调函数
curl_easy_setopt(m_pCurl, CURLOPT_NOPROGRESS, 0);
curl_easy_setopt(m_pCurl, CURLOPT_PROGRESSDATA, this);
curl_easy_setopt(m_pCurl, CURLOPT_PROGRESSFUNCTION, handleProgress);

// 跳过服务器SSL验证,不使用CA证书
curl_easy_setopt(m_pCurl, CURLOPT_SSL_VERIFYPEER, 0L);

// 验证服务器端发送的证书,默认是 2(高),1(中),0(禁用)
curl_easy_setopt(m_pCurl, CURLOPT_SSL_VERIFYHOST, 0L);
}

bool
CDownloader::start(
const
std::
string
&
strUrl,
const
std::
string
&
strLocalFile)
{
if (strUrl.empty()) return false;

if (m_bRunning == true) return true;

clear();

m_strDownloadUrl = strUrl;
m_strLocalFilePath = strLocalFile;

// 初始化libcurl
m_pCurl = curl_easy_init();
if (m_pCurl == NULL)
{
return false;
}

// 设置libcurl的选项
setOption();

// 创建文件
m_pFile = fopen(m_strLocalFilePath.c_str(), "wb");
if (m_pFile == NULL)
{
return false;
}

m_bRunning = true;

return true;
}

bool
CDownloader::stop()
{
clear();

m_bRunning = false;

return true;
}

size_t CDownloader::handleWrite(
void
*
buffer, size_t size, size_t nmemb,
void
*
userp )
{
CDownloader* pDownloader = (CDownloader*) userp;
if (pDownloader)
{
return pDownloader->onWrite(buffer, size, nmemb);
}
return 0;
}

size_t CDownloader::handleProgress(
void
*
buffer,
double
dltotal,
double
dlnow,
double
ultotal,
double
ulnow )
{
CDownloader* pDownloader = (CDownloader*) buffer;
if (pDownloader)
{
pDownloader->onProgress(dltotal, dlnow);
}
return 0;
}

size_t CDownloader::onProgress(
const
double
&
dltotal,
const
double
&
dlnow )
{
TRACE("%.2f / %.2f (%.2g %%)\n", dlnow, dltotal, dlnow*100.0/dltotal);
return 0;
}

size_t CDownloader::onWrite(
void
*
buffer, size_t size, size_t nmemb )
{
size_t return_size = fwrite(buffer, size, nmemb, m_pFile);
//std::cout << (char*) buffer << std::endl;
return return_size;
}

void
CDownloader::onDownload()
{
// 执行下载
CURLcode return_code = CURLE_OK;
return_code = curl_easy_perform(m_pCurl);

// 关闭文件
if (m_pFile)
{
fclose(m_pFile);
m_pFile = NULL;
}

// 下载失败
if (return_code != CURLE_OK)
{
return;
}

// 获取状态码
int response_code = 0;
curl_easy_getinfo(m_pCurl, CURLINFO_RESPONSE_CODE, &response_code);
if (response_code != 200)
{
return;
}
}
使用示例:
CDownloader downloader;
downloader.start(
"
http://xingke.onlinedown.net:82/down/QQ2013SP6.zip
"
,
"
QQ2013SP6.zip
"
);
downloader.run();
需要说明的是,这个类本身其实是运行于线程环境下的,因此,加入到多线程环境下,并非难事。扩展或者修改也并不是难得事情,比之WinInet的实现来说,libcurl的实现实在是简单得无话可说。
头文件:












































































实现文件:


































































































































































































使用示例:



需要说明的是,这个类本身其实是运行于线程环境下的,因此,加入到多线程环境下,并非难事。扩展或者修改也并不是难得事情,比之WinInet的实现来说,libcurl的实现实在是简单得无话可说。