使用libcurl实现的下载器-阿里云开发者社区

开发者社区> 杨粼波> 正文

使用libcurl实现的下载器

简介:
+关注继续查看
头文件:
ExpandedBlockStart.gif/**********************************************************************
* 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
ExpandedBlockStart.gif{
public:
    CDownloader(void);
    virtual ~CDownloader(void);

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

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

ExpandedSubBlockStart.gif    /// 停止下载
    virtual bool stop();

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

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

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

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

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

ExpandedSubBlockStart.gif    /// 下载回调
    void onDownload();

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

ExpandedSubBlockStart.gif    /// 清除数据
    void clear();

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

ExpandedSubBlockStart.gif    bool            m_bRunning;                ///< 运行标志

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



#endif


实现文件:
ExpandedBlockStart.gif/**********************************************************************
* 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)
ExpandedBlockStart.gif{
}


CDownloader::~CDownloader(void)
ExpandedBlockStart.gif{
    stop();
}


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


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


void CDownloader::clear()
ExpandedBlockStart.gif{
    if (m_pFile)
ExpandedSubBlockStart.gif    {
        fclose(m_pFile);
        m_pFile = NULL;
    }


    if (m_pCurl)
ExpandedSubBlockStart.gif    {
        curl_easy_cleanup(m_pCurl);
        m_pCurl = NULL;
        curl_global_cleanup();
    }


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


void CDownloader::setOption()
ExpandedBlockStart.gif{
    // 远程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)
ExpandedBlockStart.gif{
    if (strUrl.empty()) return false;

    if (m_bRunning == truereturn true;

    clear();

    m_strDownloadUrl    = strUrl;
    m_strLocalFilePath    = strLocalFile;

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


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

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


    m_bRunning = true;

    return true;
}


bool CDownloader::stop()
ExpandedBlockStart.gif{
    clear();

    m_bRunning = false;

    return true;
}


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

    return 0;
}


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

    return 0;
}


size_t CDownloader::onProgress( const double& dltotal, const double& dlnow )
ExpandedBlockStart.gif{
    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 )
ExpandedBlockStart.gif{
    size_t return_size = fwrite(buffer, size, nmemb, m_pFile);
    //std::cout << (char*) buffer << std::endl;
    return return_size;
}


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

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


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


    // 获取状态码
    int response_code = 0;
    curl_easy_getinfo(m_pCurl, CURLINFO_RESPONSE_CODE, &response_code);
    if (response_code != 200)
ExpandedSubBlockStart.gif    {
        return;
    }

}


使用示例:
CDownloader downloader;
downloader.start("http://xingke.onlinedown.net:82/down/QQ2013SP6.zip", "QQ2013SP6.zip");
downloader.run();

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

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
Pycharm远程ECS部署Django小项目
本文完成了一个简易的Django项目的部署,ECS上选用的系统是Ubuntu,所用的Django项目是笔者本科期间的课程设计,详见https://github.com/ztingz/NTCS
15 0
CentOS 7.9 基于LAMP架构搭建DISCUZ论坛
使用阿里云服务器搭建Linux服务器,并搭建基于LAMP架构的DISCUZ论坛服务,并通过内网正常的访问到自己的DISCUZ论坛界面。
6 0
如何科学的使用无影云电脑
我当时整个人都高兴的跳起来了,由于坐下的时候太着急,一屁股坐在了地上,导致我之后的一段时间都只能半只屁股坐在椅子上,带薪摸鱼的难度得到大幅度提升。 作为一名网络安全领域的博主,经常用Python做一些奇怪的操作,比如爬CSDN的热榜信息,爬b站舞蹈区的小姐姐,一边爬一边感慨中国文化的博大精深
20 0
阿里云飞天加速计划ecs服务器试用体验
关于阿里云飞天加速计划ecs服务器的试用体验
9 0
你真的了解CSS3硬件加速吗?
你真的了解CSS3硬件加速吗?
24 0
跟云服务器相比,使用高防服务器有什么好处
随着互联网的普及发展,行业建站非常普遍,无论是正规企业网站、游戏网站、购物网站,还是一些娱乐网站。网站给用户带来方便的同时,也带来了各种网络威胁,近年来网络攻击频发,网络攻击事件层出不穷,致使企业安全问题日益突出。
6 0
MQTT知识大全【科普贴】
MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于客户端与服务器之间发布/订阅(publish/subscribe)模式的"轻量级"通讯协议。为了保证通讯的安全性和可靠性,该协议基于TCP/IP协议构建。由IBM在1999年发布,最初被用于石油管道传感器与卫星的通讯连接,2014年,它正式成为一个OASIS开放标准并得到了大量开源语言的支持。
9 0
如何搭建一台供自己永久使用的服务器,永久运行自己的网站【再见 云服务器】
如何搭建一台供自己永久使用的服务器,永久运行自己的网站【再见 云服务器】
18 0
前后端分离 -- 深入浅出 Spring Boot + Vue 实现工程项目进度管理系统 Vue不过如此~
前后端分离 -- 深入浅出 Spring Boot + Vue 实现工程项目进度管理系统 Vue不过如此~
9 0
+关注
杨粼波
网游的老兵
1135
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载