牵着老婆满街逛

严以律己,宽以待人. 三思而后行.
GMail/GTalk: yanglinbo#google.com;
MSN/Email: tx7do#yahoo.com.cn;
QQ: 3 0 3 3 9 6 9 2 0 .

使用libcurl实现的上传器

头文件
/**********************************************************************
* Copyright (C) 2014 -  - All Rights Reserved
*
* 文件名称:        Uploader_LibCurl.h
* 摘    要:        上传器 - LibCurl实现
*     
* 作    者:        yanglinbo,
* 修    改:        查看文件最下方.

**********************************************************************
*/


#ifndef __Uploader_LibCurl_H__
#define __Uploader_LibCurl_H__


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


class CUploader
{
public:
    CUploader(
void);
    
virtual ~CUploader(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 handleRead(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 onUpload(void *buffer, size_t size, size_t nmemb);

    
/// 进度回调
    size_t onProgress(const double& ultotal, const double& ulnow);

    
/// 上传回调
    void onUpload();

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

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

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

    bool            m_bRunning;                ///< 运行标志

    std::string        m_strRemoteUrl;            ///< 远程链接
    std::string        m_strLocalFilePath;        ///< 本地文件路径

    size_t            m_nLocalFileSize;        ///< 本地文件大小
};



#endif

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

**********************************************************************
*/


#include 
"StdAfx.h"
#include 
"Uploader.h"
#include 
<sys/stat.h>
#include 
<fcntl.h>


CUploader::CUploader(
void)
: m_pCurl(NULL)
, m_pFile(NULL)
, m_bRunning(
false)
, m_nLocalFileSize(
0)
{
}


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


bool CUploader::run()
{
    onUpload();
    
return true;
}


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


void CUploader::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_strRemoteUrl.clear();
    m_strLocalFilePath.clear();

    m_nLocalFileSize 
= 0;
}


bool CUploader::setOption()
{
    
// 远程URL,支持 http, https, ftp
    curl_easy_setopt(m_pCurl, CURLOPT_URL, m_strRemoteUrl.c_str());

    curl_easy_setopt(m_pCurl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)m_nLocalFileSize);

    
// 设置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_UPLOAD, TRUE);

    curl_easy_setopt(m_pCurl, CURLOPT_NOSIGNAL, 
1L);
    curl_easy_setopt(m_pCurl, CURLOPT_POST, TRUE);
    curl_easy_setopt(m_pCurl, CURLOPT_FORBID_REUSE, TRUE);

    
// 上传内容回调函数
    curl_easy_setopt(m_pCurl, CURLOPT_READFUNCTION, handleRead);
    curl_easy_setopt(m_pCurl, CURLOPT_READDATA, 
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);

    
return true;
}


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

    
if (m_bRunning == truereturn true;

    clear();

    m_strRemoteUrl    
= strUrl;
    m_strLocalFilePath    
= strLocalFile;

    
// 打开文件
    m_pFile = fopen(m_strLocalFilePath.c_str(), "rb");
    
if (m_pFile == NULL)
    
{
        
return false;
    }


    
// 获取文件大小
    struct stat file_info;
    
if (fstat(fileno(m_pFile), &file_info) != 0
    
{
        
return false;
    }

    m_nLocalFileSize 
= file_info.st_size;

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


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

    m_bRunning 
= true;

    
return true;
}


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

    m_bRunning 
= false;

    
return true;
}


size_t CUploader::handleRead( 
void *buffer, size_t size, size_t nmemb, void *userp )
{
    CUploader
* pDownloader = (CUploader*) userp;
    
if (pDownloader)
    
{
        
return pDownloader->onUpload(buffer, size, nmemb);
    }

    
return 0;
}


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

    
return 0;
}


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


size_t CUploader::onUpload( 
void *buffer, size_t size, size_t nmemb )
{
    size_t return_size 
= fread(buffer, size, nmemb, m_pFile);
    
return return_size;
}


void CUploader::onUpload()
{
    
// 执行上传
    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);
}


示例代码:
CUploader uploader
uploader.start(
"ftp://upload:upload@127.0.0.1/hello.exe""C:\\fly.exe");
uploader.run();

posted on 2014-04-01 23:23 杨粼波 阅读(923) 评论(0)  编辑 收藏 引用 所属分类: 网络编程C++


只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理