zoukankan      html  css  js  c++  java
  • 使用libCurl实现断点下载

    关键部分代码如下:

    #include "curl.h"

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

    size_t CROS_DownloadDlg::getContentLengthFunc(void * ptr, size_t size, size_t nmemb, void * stream)
    {
    LONGLONG len = 0;
    int r = sscanf((const char *)ptr, "Content-Length:%I64d ",&len);
    if(r)
    *((LONGLONG *) stream) = len;
    return size * nmemb;
    }


    //根据URL获取下载文件大小
    LONGLONG CROS_DownloadDlg::getDownloadFileSize(const char*  url)
    {
    double lensize = 0.0;
    for(int iTry = 0 ; iTry < 3 ; iTry ++)//由于curl_easy_perform可能会有偶发性的CURLE_WRITE_ERROR错误,所以添加重试机制
    {
    CURL *handle = curl_easy_init();
    curl_easy_setopt(handle, CURLOPT_URL, url);
    curl_easy_setopt(handle, CURLOPT_HEADER, 1);
    curl_easy_setopt(handle, CURLOPT_FOLLOWLOCATION, 1);
    curl_easy_setopt(handle, CURLOPT_NOBODY, 1);
    CURLcode res = curl_easy_perform(handle), resGetInfo = CURLE_OK;
    if (res == CURLE_OK) {
    resGetInfo = curl_easy_getinfo(handle, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &lensize);
    if(CURLE_OK == resGetInfo){
    curl_easy_cleanup(handle);
    return (LONGLONG)lensize;
    }
    }
    curl_easy_cleanup(handle);
    Sleep(200);
    }
    return 0;
    }


    size_t CROS_DownloadDlg::downLoadPackage(void *ptr, size_t size, size_t nmemb, void *userdata)
    {
    if(!ptr || !userdata)
    return 0;
    return fwrite(ptr, size, nmemb, (FILE *)userdata);
    }


    int CROS_DownloadDlg::assetsManagerProgressFunc(void *ptr, double totalToDownload, double nowDownloaded, double totalToUpLoad, double nowUpLoaded)
    {
    if(m_bStop)
    return -1;
    if(totalToDownload > 0.0)
    {
    CROS_DownloadDlg* pDlg = (CROS_DownloadDlg*)ptr;
    pDlg->m_lProcessSize = (LONGLONG)nowDownloaded;
    pDlg->SendMessage(WM_DOWNLOADPROC_MSG, 1, 0);
    }
    return 0;
    }


    /*
    0 设置总大小
    1 设置当前下载
    2 下载完成
    3 用户停止下载,其他异常终止下载
    4 网络问题引发的下载异常
    5 设备断开连接
    6 磁盘剩余空间不足
    */
    UINT CROS_DownloadDlg::DownloadProc(LPVOID lpParam)

    {

    //////////////////////////////////////////////////////////////////////////使用CURL实现下载
    string sURL = CStringConverter::Unicode2Ansi(strURL.GetString()), sSavePath = CStringConverter::Unicode2Ansi(strSavePath.GetString());


    LONGLONG local_file_len = GetFileSize(strSavePath);
    pDlg->m_lLocalFileCurSize = local_file_len;
    curl_global_init(CURL_GLOBAL_DEFAULT);
    LONGLONG remote_file_len = getDownloadFileSize(sURL.c_str());
    if(!remote_file_len)
    {
    pDlg->SendMessage(WM_DOWNLOADPROC_MSG, 4, 0);//网络问题获取失败
    return 0;
    }
    pDlg->m_lTotalSize = remote_file_len;
    pDlg->SendMessage(WM_DOWNLOADPROC_MSG, 0, 0);
    if(local_file_len == remote_file_len)
    {
    pDlg->SendMessage(WM_DOWNLOADPROC_MSG, 2, 0);
    return 0;
    }
    //得到准确大小后应判断strSavePath空间是否足够先
    if(remote_file_len >= (pDlg->m_ulDiskSpaceMax))
    {
    pDlg->SendMessage(WM_DOWNLOADPROC_MSG, 6, 0);
    return 0;
    }
    FILE *fp = fopen(sSavePath.c_str(), "ab+");
    if(!fp)
    {
    pDlg->SendMessage(WM_DOWNLOADPROC_MSG, 3, 0);
    return 0;
    }
    LONGLONG filesize = 0;
    m_pCurl = curl_easy_init();//curl初始化
    CURLcode res;
    curl_easy_setopt(m_pCurl, CURLOPT_URL, sURL.c_str());//设定curl的链接
    curl_easy_setopt(m_pCurl, CURLOPT_CONNECTTIMEOUT,5);//设置连接超时,单位秒
    curl_easy_setopt(m_pCurl, CURLOPT_HEADERFUNCTION,getContentLengthFunc);
    curl_easy_setopt(m_pCurl, CURLOPT_HEADERDATA, &filesize);
    curl_easy_setopt(m_pCurl, CURLOPT_RESUME_FROM_LARGE, local_file_len);//断点下载设置
    curl_easy_setopt(m_pCurl, CURLOPT_WRITEFUNCTION, downLoadPackage);
    curl_easy_setopt(m_pCurl, CURLOPT_WRITEDATA, fp);//设置将data写入到文件流fp中
    curl_easy_setopt(m_pCurl, CURLOPT_FOLLOWLOCATION, 1L);//设置重定位URL,使用自动跳转,返回的头部中有Location(一般直接请求的url没找到),则继续请求Location对应的数据
    curl_easy_setopt(m_pCurl, CURLOPT_MAXREDIRS,5);//查找次数,防止查找太深
    curl_easy_setopt(m_pCurl, CURLOPT_NOPROGRESS, false);//设为false 下面才能设置进度响应函数
    curl_easy_setopt(m_pCurl, CURLOPT_PROGRESSFUNCTION, assetsManagerProgressFunc);//进度响应函数
    curl_easy_setopt(m_pCurl, CURLOPT_PROGRESSDATA, pDlg);//数据传输的对象
    curl_easy_setopt(m_pCurl, CURLOPT_VERBOSE,1L);
    res = curl_easy_perform(m_pCurl);
    curl_easy_cleanup(m_pCurl);
    curl_global_cleanup();
    m_pCurl = NULL;
    if (res != CURLE_OK)
    {
    fclose(fp);
    if(res == CURLE_ABORTED_BY_CALLBACK)//点击停止下载
    pDlg->SendMessage(WM_DOWNLOADPROC_MSG, 3, 0);
    else if(res == CURLE_RECV_ERROR)//断网     /* 56 - failure in receiving network data */
    pDlg->SendMessage(WM_DOWNLOADPROC_MSG, 4, 0);
    else
    pDlg->SendMessage(WM_DOWNLOADPROC_MSG, 3, 0);
    return 0;
    }
    fclose(fp);
    pDlg->SendMessage(WM_DOWNLOADPROC_MSG, 2, 0);
    return 0;

    }

    void CROS_DownloadDlg::OnClickBtnStop()
    {
    if(m_pCurl){
    curl_easy_pause(m_pCurl, CURLPAUSE_RECV);
    if(IDYES == ShowMessage(IDS_DEF_ROS_SURE_TO_STOP, CiPhoneUtil::GetApplicationName(), SM_ICON_QUESTION|SM_YES_AND_NO)){
    m_btnStop.EnableWindow(FALSE);
    m_bStop = true;
    return;
    }
    curl_easy_pause(m_pCurl, CURLPAUSE_RECV_CONT);
    }
    }

     
    http://blog.csdn.net/dingxz105090/article/details/52621614
  • 相关阅读:
    iOS nsstring 截取字符前后字符串
    iOS 计算时间差
    Android的ProgressBar
    Android:OptionMenu
    eclipse the user operation is waiting for building workspace" to complete
    Android存储之SQLiteDatbase
    Android保存之SharedPreferences
    pkg_utility
    Oracle同义词 synonyms
    xzzx
  • 原文地址:https://www.cnblogs.com/findumars/p/5928683.html
Copyright © 2011-2022 走看看