libcurl断点下载

 

开发需要写了一个处理curl 下载的c++类,内含有多个静态方法和实例方法,写在这里留给有需求的同学

 

头文件



CURLHelper.h



enum CURLHelperStateType

{

    CURLHelper_START = 0,

    CURLHelper_PROGRESS = 1,

    CURLHelper_COMPLETE = 2,

    CURLHelper_UNKNOW = 99

};



class CURLHelper

{

public:

    static std::string getHttpString(const char * url);



    static long getDownloadFileSize(const char *url);

    

    static long getLocalFileSize(const char *localpath);

    

    

    CURLHelper();

    ~CURLHelper();

    

    void downloadFile(const char *url,const char *localpath);

    

    void downloadProgressCallback(double percent);

    

    long getTotalFileSize();

    

    CURLHelperStateType getState();

    

    double getPercent();

    

    void doDownload();

private:

    string m_url;

    string m_local_path;

    

    double m_fileTotalSize;

//    double m_currentFileSize;

    

    double m_percent;

    

    pthread_t *pDownloadThread;



    int reDownloadCount;

    CURLHelperStateType m_currentState;

};
/**

 *  获取服务器文件的字符 ,阻塞式

 *  @param url

 *  @return

 */

string CURLHelper::getHttpString(const char *url)

{

    std::string str = "";

    CURL *_curl = curl_easy_init();

    if (! _curl)

    {

        CCLOG("can not init curl");

        return str;

    }

    curl_easy_setopt(_curl, CURLOPT_URL, url);

    curl_easy_setopt(_curl, CURLOPT_SSL_VERIFYPEER, 0L);

    curl_easy_setopt(_curl, CURLOPT_WRITEFUNCTION, getCharCode);

    curl_easy_setopt(_curl, CURLOPT_WRITEDATA, &str);

    

    CURLcode res = curl_easy_perform(_curl);

    if (res != CURLE_OK)

    {

        CCLOG("can not get version file content, error code is %d", res);

        curl_easy_cleanup(_curl);

        return str;

    }

    curl_easy_cleanup(_curl);

    return str;

}

/**

 *  获取服务器上的文件物理大小

 *  @param url

 *  @return

 */

long CURLHelper::getDownloadFileSize(const char *url)

{

    double downloadFileLenth = 0;

    CURL *handle = curl_easy_init();

    curl_easy_setopt(handle, CURLOPT_URL, url);

    curl_easy_setopt(handle, CURLOPT_HEADER, 1);    //只需要header头

    curl_easy_setopt(handle, CURLOPT_NOBODY, 1);    //不需要body

    if (curl_easy_perform(handle) == CURLE_OK)

    {

        curl_easy_getinfo(handle, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &downloadFileLenth);

    }

    else

    {

        downloadFileLenth = -1;

    }

    return downloadFileLenth;

}

/**

 *  获取本地文件大小

 *  @param localpath

 *  @return

 */

long CURLHelper::getLocalFileSize(const char *localpath)

{

    curl_off_t local_file_len = 0;

    struct stat file_info;

    if(stat(localpath, &file_info) == 0)

    {

        local_file_len =  file_info.st_size;

    }

    return local_file_len;

}



/* 保存下载文件 */



size_t wirtefunc(void *ptr, size_t size, size_t nmemb, void *stream)

{

    FILE *fp = (FILE*)stream;

    size_t written = fwrite(ptr, size, nmemb, fp);

    return written;

}

/* 下载回调的计算进度条的函数 */

static int progress_func(void *ptr, double totalToDownload, double nowDownloaded, double totalToUpLoad, double nowUpLoaded)

{

    CURLHelper *helper = (CURLHelper*)ptr;

    double curpercent = 100 * nowDownloaded / totalToDownload;

    

    helper->downloadProgressCallback(curpercent);

    return 0;

}



void CURLHelper::doDownload()

{

    do

    {

        string tmpPath = m_local_path + ".tmp";

        FILE *localFile = NULL;

        

        double m_currentTmpSize = CURLHelper::getLocalFileSize(tmpPath.c_str());

        

        if (m_currentTmpSize > 0)

        {

            localFile = fopen(tmpPath.c_str(), "ab+");

            CCLOG("断点下载模式");

        }

        else

        {

            localFile = fopen(tmpPath.c_str(), "wb+");

        }

        int cc = error_no();

        if (!localFile)

        {

            break;

        }

        m_currentState = CURLHelper_PROGRESS;

        CURL *curlhandle = curl_easy_init();

        curl_easy_setopt(curlhandle, CURLOPT_URL, m_url.c_str());



        //写函数回调

        curl_easy_setopt(curlhandle, CURLOPT_WRITEDATA, localFile);

        curl_easy_setopt(curlhandle, CURLOPT_WRITEFUNCTION, wirtefunc);

        //断点下载

        curl_easy_setopt(curlhandle, CURLOPT_RESUME_FROM_LARGE, m_currentTmpSize);

        //下载进度回调

        curl_easy_setopt(curlhandle, CURLOPT_NOPROGRESS, 0L);

        curl_easy_setopt(curlhandle, CURLOPT_PROGRESSFUNCTION, progress_func);

        curl_easy_setopt(curlhandle, CURLOPT_PROGRESSDATA, this);



        CURLcode res = curl_easy_perform(curlhandle);

        fclose(localFile);

        curl_easy_cleanup(curlhandle);



        if (res == CURLE_OK)

        {

            //文件改名

            int result = rename(tmpPath.c_str(), m_local_path.c_str());

            int e = error_no();

            if (result == 0)

            {

                CCLOG("改名成功");

            }

            else

            {

                CCLOG("rename failed %d",e);

            }

        }

        else

        {

            CCLOG("下载失败,CURLcode %d",res);

            if (reDownloadCount < 3)

            {

                //直接删除缓存文件

                int removeCode = remove(tmpPath.c_str());

                CCLOG("下载失败,删除tmp文件,并重新下载 %d",removeCode);

                reDownloadCount++;

                m_currentState = CURLHelper_START;

                doDownload();

                return;

            }

        }



    }

    while (0);

    m_currentState = CURLHelper_COMPLETE;

}





CURLHelper::CURLHelper()

{

    m_currentState = CURLHelper_UNKNOW;

    pDownloadThread = NULL;

    m_percent = 0;

    reDownloadCount = 0;

}



CURLHelper::~CURLHelper()

{

    CCLOG("~CURLHelper");

    if (pDownloadThread)

    {

        delete pDownloadThread;

    }

}

long CURLHelper::getTotalFileSize()

{

    return m_fileTotalSize;

}

CURLHelperStateType CURLHelper::getState()

{

    return m_currentState;

}



static void *thread_downloadFiles(void* data)

{

    CURLHelper *helper = (CURLHelper*)data;

    helper->doDownload();

    return NULL;

}



void CURLHelper::downloadFile(const char *url, const char *localpath)

{

    m_url = url;

    m_local_path = localpath;

    m_fileTotalSize = CURLHelper::getDownloadFileSize(url);

    m_percent = 0;

    //记录当前状态

    m_currentState = CURLHelper_START;

    //开启线程下载

    pDownloadThread = new pthread_t();

    pthread_create(&(*pDownloadThread), NULL, thread_downloadFiles, (void*)this);

}

void CURLHelper::downloadProgressCallback(double percent)

{

    m_percent = percent;

}

double CURLHelper::getPercent()

{

    return m_percent;

}

 

 

你可能感兴趣的:(curl)