curl 一个使用例子

#include <iostream>
#define Main main
#include <string>
#include <assert.h>
#include <curl/curl.h>
#include <curl/easy.h>

#pragma comment(lib,"libcurl.lib")
#pragma comment(lib,"ws2_32.lib")

using namespace std;

class CLibcurlCallback
{
public:
    virtual void Progress(void* lpParam, double dTotal, double bLoaded) = 0;
};

enum LibcurlFlag
{
    Lf_None = 0,
    Lf_Download,
    Lf_Post,
    Lf_Get,
};

class CLibcurl
{
public:
    CLibcurl(void);
    ~CLibcurl(void);
    /******************************************************************************
    *封装类的外部调用接口
    */
    bool SetPorts(LONG port);                                            //设置连接端口号
    bool SetTimeout(int nSecond);                                        //设置执行超时(秒)
    bool SetConnectTimeout(int nSecond);                                //设置连接超时(秒)
    bool SetUserAgent(LPCSTR lpAgent);                                    //设置用户代理
    bool SetResumeFrom(LONG lPos);                                        //设置断点续传起始位置
    bool SetResumeFromLarge(LONGLONG llPos);                            //设置断点续传起始位置,针对大文件
    bool AddHeader(LPCSTR lpKey, LPCSTR lpValue);                        //添加自定义头
    void ClearHeaderList();                                                //清理HTTP列表头
    bool SetCookie(LPCSTR lpCookie);                                    //设置HTTP请求cookie
    bool SetCookieFile(LPCSTR lpFilePath);                                //设置HTTP请求cookie文件
    const char* GetError()const;                                        //获取错误详细信息
    void SetCallback(CLibcurlCallback* pCallback, void* lpParam);        //设置下载进度回调
    bool DownloadToFile(LPCSTR lpUrl, LPCSTR lpFile);                    //下载文件到磁盘
    bool Post(LPCSTR lpUrl, LPCSTR lpData);                                //Post 字符串数据
    bool Post(LPCSTR lpUrl, unsigned char* lpData, unsigned int nSize); //Post 字符串或者二进制数据
    bool Get(LPCSTR lpUrl);                                                //Get 请求
    const string& GetRespons()const;                                    //获取Post/Get请求返回数据
    const char*    GetResponsPtr()const;                                    //获取Post/Get请求返回数据

protected:
    static size_t    WriteCallback(void* pBuffer, size_t nSize, size_t nMemByte, void* pParam);
    static size_t    HeaderCallback(void* pBuffer, size_t nSize, size_t nMemByte, void* pParam);
    static int        ProgressCallback(void *pParam, double dltotal, double dlnow, double ultotal, double ulnow);

private:
    CURL    *m_pCurl;
    LONG    m_nPort;
    HANDLE    m_hFile;
    CURLcode m_curlCode;
    string    m_strRespons;
    LibcurlFlag m_lfFlag;
    curl_slist *m_curlList;
    void    *m_pCallbackParam;
    CLibcurlCallback    *m_pCallback;
};
class CLibcurlCallbackEx
    : public CLibcurlCallback
{
public:
    virtual void Progress(void* lpParam, double dTotal, double dLoaded)
    {
        if (dTotal == 0.0)
            return;
        double bPercent = (dLoaded / dTotal) * 100;
        printf("下载进度:%0.2lf%%\n", bPercent);
    }

};

class CommonTools
{
public:
    CommonTools() {}
    ~CommonTools() {}
public:
    static size_t receive_data(void *contents, size_t size, size_t nmemb, void *stream);
    // HTTP 下载文件的回掉函数
    static size_t writedata2file(void *ptr, size_t size, size_t nmemb, FILE *stream);
    // 文件下载接口
    static int download_file(const char* url, const char outfilename[FILENAME_MAX]);
    // http get 请求
    static CURLcode HttpGet(const std::string & strUrl, std::string & strResponse, int nTimeout);
    // htpp post 请求
    static CURLcode HttpPost(const std::string & strUrl, std::string szJson, std::string & strResponse, int nTimeout);
};

int Main()
{
    //string url("http://t.weather.sojson.com/api/weather/city/101270101");
    //string buf;
    //CommonTools::HttpGet(url, buf, 300);

    //FILE *File = NULL;
    //fopen_s(&File, "test.json", "wb+");
    //if (File)
    //{
    //    fwrite(buf.c_str(), buf.length(), 1, File);
    //}
    //fclose(File);
    //File = NULL;


    system("pause");
    return 0;
}




CLibcurl::CLibcurl(void)
    : m_pCurl(NULL)
    , m_nPort(80)
    , m_hFile(INVALID_HANDLE_VALUE)
    , m_pCallback(NULL)
    , m_pCallbackParam(NULL)
    , m_curlCode(CURLE_OK)
    , m_lfFlag(Lf_None)
    , m_curlList(NULL)
{
    m_pCurl = curl_easy_init();
    curl_easy_setopt(m_pCurl, CURLOPT_WRITEFUNCTION, WriteCallback);
    curl_easy_setopt(m_pCurl, CURLOPT_WRITEDATA, this);
}

CLibcurl::~CLibcurl(void)
{
    ClearHeaderList();
    curl_easy_cleanup(m_pCurl);
    if (m_hFile != INVALID_HANDLE_VALUE)
    {
        CloseHandle(m_hFile);
    }
}

bool CLibcurl::SetPorts(LONG port)
{
    if (port == m_nPort)
        return true;
    m_nPort = port;
    m_curlCode = curl_easy_setopt(m_pCurl, CURLOPT_PORT, m_nPort);
    return CURLE_OK == m_curlCode;
}

bool CLibcurl::SetTimeout(int nSecond)
{
    if (nSecond < 0)
        return false;
    m_curlCode = curl_easy_setopt(m_pCurl, CURLOPT_TIMEOUT, nSecond);
    return CURLE_OK == m_curlCode;
}

bool CLibcurl::SetConnectTimeout(int nSecond)
{
    if (nSecond < 0)
        return false;
    m_curlCode = curl_easy_setopt(m_pCurl, CURLOPT_CONNECTTIMEOUT, nSecond);
    return CURLE_OK == m_curlCode;
}

bool CLibcurl::SetUserAgent(LPCSTR lpAgent)
{
    if (NULL == lpAgent)
        return false;
    int nLen = strlen(lpAgent);
    if (nLen == 0)
        return false;
    m_curlCode = curl_easy_setopt(m_pCurl, CURLOPT_USERAGENT, lpAgent);
    return CURLE_OK == m_curlCode;
}

bool CLibcurl::SetResumeFrom(LONG lPos)
{
    if (lPos < 0)
        return false;
    m_curlCode = curl_easy_setopt(m_pCurl, CURLOPT_RESUME_FROM, lPos);
    return CURLE_OK == m_curlCode;
}

bool CLibcurl::SetResumeFromLarge(LONGLONG llPos)
{
    if (llPos < 0)
        return false;
    m_curlCode = curl_easy_setopt(m_pCurl, CURLOPT_RESUME_FROM_LARGE, llPos);
    return CURLE_OK == m_curlCode;
}

bool CLibcurl::AddHeader(LPCSTR lpKey, LPCSTR lpValue)
{
    assert(lpKey != NULL && lpValue != NULL);
    int nLen1 = strlen(lpKey), nLen2 = strlen(lpValue);
    assert(nLen1 > 0 && nLen2 > 0);
    string strHeader(lpKey);
    strHeader.append(": ");
    strHeader.append(lpValue);
    m_curlList = curl_slist_append(m_curlList, strHeader.c_str());
    m_curlCode = curl_easy_setopt(m_pCurl, CURLOPT_HTTPHEADER, m_curlList);
    return CURLE_OK == m_curlCode;
}

void CLibcurl::ClearHeaderList()
{
    if (m_curlList)
    {
        curl_slist_free_all(m_curlList);
        m_curlList = NULL;
    }
}

bool CLibcurl::SetCookie(LPCSTR lpCookie)
{
    assert(lpCookie != NULL);
    m_curlCode = curl_easy_setopt(m_pCurl, CURLOPT_COOKIE, lpCookie);
    return CURLE_OK == m_curlCode;
}

bool CLibcurl::SetCookieFile(LPCSTR lpFilePath)
{
    assert(lpFilePath != NULL);
    m_curlCode = curl_easy_setopt(m_pCurl, CURLOPT_COOKIEFILE, lpFilePath);
    return CURLE_OK == m_curlCode;
}

const char* CLibcurl::GetError() const
{
    return curl_easy_strerror(m_curlCode);
}

void CLibcurl::SetCallback(CLibcurlCallback* pCallback, void* lpParam)
{
    m_pCallbackParam = lpParam;
    m_pCallback = pCallback;
}

bool CLibcurl::DownloadToFile(LPCSTR lpUrl, LPCSTR lpFile)
{
    CURLcode code = curl_easy_setopt(m_pCurl, CURLOPT_URL, lpUrl);
    DeleteFileA(lpFile);
    m_hFile = CreateFileA(lpFile, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    if (INVALID_HANDLE_VALUE == m_hFile)
    {
        return FALSE;
    }
    curl_easy_setopt(m_pCurl, CURLOPT_NOPROGRESS, 0);
    curl_easy_setopt(m_pCurl, CURLOPT_PROGRESSFUNCTION, ProgressCallback);
    curl_easy_setopt(m_pCurl, CURLOPT_PROGRESSDATA, this);
    m_lfFlag = Lf_Download;
    //开始执行请求
    m_curlCode = curl_easy_perform(m_pCurl);
    return CURLE_OK == m_curlCode;
}

bool CLibcurl::Post(LPCSTR lpUrl, LPCSTR lpData)
{
    assert(lpData != NULL);
    curl_easy_setopt(m_pCurl, CURLOPT_POST, 1);
    curl_easy_setopt(m_pCurl, CURLOPT_POSTFIELDS, lpData);
    //curl_easy_setopt(m_pCurl, CURLOPT_POSTFIELDSIZE, lpData);
    curl_easy_setopt(m_pCurl, CURLOPT_URL, lpUrl);
    m_lfFlag = Lf_Post;
    m_strRespons.clear();
    m_curlCode = curl_easy_perform(m_pCurl);
    return CURLE_OK == m_curlCode;
}

bool CLibcurl::Post(LPCSTR lpUrl, unsigned char* lpData, unsigned int nSize)
{
    assert(lpData != NULL && nSize > 0);
    curl_easy_setopt(m_pCurl, CURLOPT_POST, 1);
    curl_easy_setopt(m_pCurl, CURLOPT_POSTFIELDS, lpData);
    curl_easy_setopt(m_pCurl, CURLOPT_POSTFIELDSIZE, nSize);
    curl_easy_setopt(m_pCurl, CURLOPT_URL, lpUrl);
    m_lfFlag = Lf_Post;
    m_strRespons.clear();
    m_curlCode = curl_easy_perform(m_pCurl);
    return CURLE_OK == m_curlCode;
}

bool CLibcurl::Get(LPCSTR lpUrl)
{
    assert(lpUrl != NULL);
    curl_easy_setopt(m_pCurl, CURLOPT_HTTPGET, 1);
    curl_easy_setopt(m_pCurl, CURLOPT_URL, lpUrl);
    curl_easy_setopt(m_pCurl, CURLOPT_FOLLOWLOCATION, 1);//支持重定向
    curl_easy_setopt(m_pCurl, CURLOPT_SSL_VERIFYPEER, 0L);
    curl_easy_setopt(m_pCurl, CURLOPT_SSL_VERIFYHOST, 0L);
    m_lfFlag = Lf_Get;
    m_strRespons.clear();
    m_curlCode = curl_easy_perform(m_pCurl);
    return CURLE_OK == m_curlCode;
}

const string& CLibcurl::GetRespons() const
{
    return m_strRespons;
}

const char* CLibcurl::GetResponsPtr() const
{
    return m_strRespons.c_str();
}

size_t CLibcurl::WriteCallback(void* pBuffer, size_t nSize, size_t nMemByte, void* pParam)
{
    //把下载到的数据以追加的方式写入文件(一定要有a,否则前面写入的内容就会被覆盖了)
    CLibcurl* pThis = (CLibcurl*)pParam;
    DWORD dwWritten = 0;
    switch (pThis->m_lfFlag)
    {
    case Lf_Download://下载
    {
        if (pThis->m_hFile == INVALID_HANDLE_VALUE)
            return 0;
        if (!WriteFile(pThis->m_hFile, pBuffer, nSize*nMemByte, &dwWritten, NULL))
            return 0;
    }
    break;
    case Lf_Post://Post数据
    case Lf_Get://Get数据
    {
        pThis->m_strRespons.append((const char*)pBuffer, nSize*nMemByte);
        dwWritten = nSize * nMemByte;
    }
    break;
    case Lf_None://未定义
        break;
    }
    return dwWritten;
}

size_t CLibcurl::HeaderCallback(void* pBuffer, size_t nSize, size_t nMemByte, void* pParam)
{
    CLibcurl* pThis = (CLibcurl*)pParam;
    return 0;
}

int CLibcurl::ProgressCallback(void *pParam, double dltotal, double dlnow, double ultotal, double ulnow)
{
    CLibcurl* pThis = (CLibcurl*)pParam;
    if (pThis->m_pCallback)
    {
        pThis->m_pCallback->Progress(pThis->m_pCallbackParam, dltotal, dlnow);
    }
    return 0;
}


size_t CommonTools::receive_data(void *contents, size_t size, size_t nmemb, void *stream) {
    string *str = (string*)stream;
    (*str).append((char*)contents, size*nmemb);
    return size * nmemb;
}

size_t CommonTools::writedata2file(void *ptr, size_t size, size_t nmemb, FILE *stream) {
    size_t written = fwrite(ptr, size, nmemb, stream);
    return written;
}

int CommonTools::download_file(const char* url, const char outfilename[FILENAME_MAX]) {
    CURL *curl;
    FILE *fp;
    CURLcode res;
    /*   调用curl_global_init()初始化libcurl  */
    res = curl_global_init(CURL_GLOBAL_ALL);
    if (CURLE_OK != res)
    {
        printf("init libcurl failed.");
        curl_global_cleanup();
        return -1;
    }
    /*  调用curl_easy_init()函数得到 easy interface型指针  */
    curl = curl_easy_init();
    if (curl) {
        fp = fopen(outfilename, "wb");

        /*  调用curl_easy_setopt()设置传输选项 */
        res = curl_easy_setopt(curl, CURLOPT_URL, url);
        if (res != CURLE_OK)
        {
            fclose(fp);
            curl_easy_cleanup(curl);
            return -1;
        }
        /*  根据curl_easy_setopt()设置的传输选项,实现回调函数以完成用户特定任务  */
        res = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CommonTools::writedata2file);
        if (res != CURLE_OK) {
            fclose(fp);
            curl_easy_cleanup(curl);
            return -1;
        }
        /*  根据curl_easy_setopt()设置的传输选项,实现回调函数以完成用户特定任务  */
        res = curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
        if (res != CURLE_OK)
        {
            fclose(fp);
            curl_easy_cleanup(curl);
            return -1;
        }

        res = curl_easy_perform(curl);
        // 调用curl_easy_perform()函数完成传输任务
        fclose(fp);
        /* Check for errors */
        if (res != CURLE_OK) {
            fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
            curl_easy_cleanup(curl);
            return -1;
        }

        /* always cleanup */
        curl_easy_cleanup(curl);
        // 调用curl_easy_cleanup()释放内存

    }
    curl_global_cleanup();
    return 0;
}

CURLcode CommonTools::HttpGet(const std::string & strUrl, std::string & strResponse, int nTimeout) {
    CURLcode res;
    CURL* pCURL = curl_easy_init();

    if (pCURL == NULL) {
        return CURLE_FAILED_INIT;
    }

    curl_easy_setopt(pCURL, CURLOPT_URL, strUrl.c_str());
    //curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
    curl_easy_setopt(pCURL, CURLOPT_NOSIGNAL, 1L);
    curl_easy_setopt(pCURL, CURLOPT_TIMEOUT, nTimeout);
    curl_easy_setopt(pCURL, CURLOPT_NOPROGRESS, 1L);
    curl_easy_setopt(pCURL, CURLOPT_WRITEFUNCTION, CommonTools::receive_data);
    curl_easy_setopt(pCURL, CURLOPT_WRITEDATA, (void*)&strResponse);
    res = curl_easy_perform(pCURL);
    curl_easy_cleanup(pCURL);
    return res;
}

CURLcode CommonTools::HttpPost(const std::string & strUrl, std::string szJson, std::string & strResponse, int nTimeout) {
    CURLcode res;
    char szJsonData[1024];
    memset(szJsonData, 0, sizeof(szJsonData));
    strcpy(szJsonData, szJson.c_str());
    CURL* pCURL = curl_easy_init();
    struct curl_slist* headers = NULL;
    if (pCURL == NULL) {
        return CURLE_FAILED_INIT;
    }

    CURLcode ret;
    ret = curl_easy_setopt(pCURL, CURLOPT_URL, strUrl.c_str());
    //    std::cout << ret << std::endl;

    ret = curl_easy_setopt(pCURL, CURLOPT_POST, 1L);
    headers = curl_slist_append(headers, "content-type:application/json");

    ret = curl_easy_setopt(pCURL, CURLOPT_HTTPHEADER, headers);

    ret = curl_easy_setopt(pCURL, CURLOPT_POSTFIELDS, szJsonData);
    //curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
    ret = curl_easy_setopt(pCURL, CURLOPT_TIMEOUT, nTimeout);

    ret = curl_easy_setopt(pCURL, CURLOPT_WRITEFUNCTION, CommonTools::receive_data);

    ret = curl_easy_setopt(pCURL, CURLOPT_WRITEDATA, (void*)&strResponse);

    res = curl_easy_perform(pCURL);
    curl_easy_cleanup(pCURL);
    return res;
}

 

posted @ 2019-11-02 09:19  YZFHKMS-X  阅读(975)  评论(0编辑  收藏  举报