curl下载示例

.h

    static bool curlDownloadFile(const std::string &remotepath,
                                 const std::string &localpath,
                                 ProgressData &progressdata,
                                 downloadProgressCallBack cb = NULL,
                                 LoadType type = HTTP,
                                 char* user_pwd = NULL,
                                 char *port = NULL,
                                 bool resume = false,
                                 long timeout = 5,
                                 long tries = 3);

.cpp

int  defaultDownloadProgressFunc(char *progress_data,
                                                 double dltotal,double dlnow,
                                                 double ultotal,double ulnow)
{
    ProgressData* pd = (ProgressData*)progress_data;
    pd->ret.dresult.dlnow = dlnow;
    pd->ret.dresult.dltotal = dltotal;
    if(!(dltotal - 0.0))
        pd->ret.dresult.downloadgdrate = (dlnow)*100.0/( dltotal);
    else
        pd->ret.dresult.downloadgdrate = 0.0;

    std::cout << dlnow << "<--->" << dltotal << std::endl;
    return  0;
}

#if 0
//阻塞型下载
bool curlDownloadFile(const std::string& remotepath,
                                      const std::string& localpath,
                                      ProgressData& progressdata,
                                      downloadProgressCallBack cb, /*progress callback function*/
                                      LoadType type,char* user_pwd,char *port,
                                      bool resume, long timeout , long tries )
{

    // 文件名包含中文会导致文件下载失败


    // printf("%s %d : %s  %s \n",__FUNCTION__,__LINE__,localpath,remotepath);
    std::cout << __FUNCTION__ <<__LINE__ << "    " << remotepath << "   " << localpath << std::endl;

    CURL *curlhandle = NULL;
    // curl_global_init(CURL_GLOBAL_ALL);

    curlhandle = curl_easy_init();
    if(!curlhandle){  return false; }

    FILE *f;
    long filesize =0 ;
    CURLcode r = CURLE_GOT_NOTHING;

    struct myprogress prog;
    char *progress_data = (char*) &prog;
    long intiSize = 0;
    FILE *file = fopen(localpath.c_str(),"wb");
    if(!file){
        perror(" open failed.\n");
        return r;
    }

    intiSize = filelength(fileno(file));
    fclose(file);
    prog.local_file_len = intiSize;


    // if( prog.local_file_len > 0) resume  = 1;

    f = fopen(localpath.c_str(), "ab+");
    if ( NULL == f ) {
        perror(NULL);
        return false;
    }


    /// 解决传参中包含中文乱码的问题
    using namespace  TiangongCloud;
    QString remotePathQstring = str2qstr(remotepath);
    QStringList lst = remotePathQstring.split("/");
    lst.removeLast();
    QString rFileName = lst.last();
    QFileInfo info(remotePathQstring);
    QString _baseName = info.baseName();
    QString _surfix = info.suffix();

    qDebug() << __FUNCTION__ << __LINE__ << _baseName << _surfix;

    /// basename可能是中文,必须转码

    QString prePath = lst.join("/");
    string param;
    char * escape_control = curl_escape(_baseName.toStdString().c_str(), _baseName.length());
    param = string(escape_control);
    curl_free(escape_control);

    // %E8%BD%B4-PMI.par
    // %D6%E1-PM.par
    // string dlurl = qstr2str(prePath) + "/" + param + + "." + _surfix.toStdString() + rFileName.toStdString();
    // std::cout << __FUNCTION__ <<__LINE__ << "    " <<  dlurl << std::endl;

    // curl_easy_setopt(curlhandle, CURLOPT_URL, remotepath );
    curl_easy_setopt(curlhandle, CURLOPT_URL, string(string_To_UTF8(remotepath)).c_str()  );

    std::cout << "++++++++++++++++++ " << __FUNCTION__ << "   " << __LINE__ << "  "
              << remotepath << "    " << string_To_UTF8(remotepath) << std::endl;

    if(timeout)
        curl_easy_setopt(curlhandle, CURLOPT_CONNECTTIMEOUT, timeout);
    curl_easy_setopt(curlhandle, CURLOPT_HEADERFUNCTION, &sdkcommucation::getcontentlengthfunc);
    curl_easy_setopt(curlhandle, CURLOPT_HEADERDATA, &filesize);
    curl_easy_setopt(curlhandle, CURLOPT_RESUME_FROM_LARGE, resume ? prog.local_file_len : 0);
    curl_easy_setopt(curlhandle, CURLOPT_WRITEDATA, f);
    curl_easy_setopt(curlhandle, CURLOPT_WRITEFUNCTION, &sdkcommucation::write_data);

    if(cb)
        curl_easy_setopt(curlhandle, CURLOPT_PROGRESSFUNCTION, cb);
    else
        curl_easy_setopt(curlhandle, CURLOPT_PROGRESSFUNCTION, defaultDownloadProgressFunc);

    curl_easy_setopt(curlhandle, CURLOPT_PROGRESSDATA, &progressdata);

    if(FTP == type){
        /* "name:password" to use when fetching. */
        curl_easy_setopt(curlhandle, CURLOPT_USERPWD, user_pwd);
        curl_easy_setopt(curlhandle, CURLOPT_FTPPORT,port ? port : "-");
        curl_easy_setopt(curlhandle, CURLOPT_FTP_CREATE_MISSING_DIRS, 0L);
    }

    curl_easy_setopt(curlhandle, CURLOPT_SSL_VERIFYPEER, 0);
    curl_easy_setopt(curlhandle, CURLOPT_SSL_VERIFYHOST, 0);
    curl_easy_setopt(curlhandle, CURLOPT_NOPROGRESS, 0L);
    curl_easy_setopt(curlhandle, CURLOPT_VERBOSE, 1L);

    for(int c = 0; (r != CURLE_OK) && (c < tries); c++) {
        r = curl_easy_perform(curlhandle);
    }

    if (r != CURLE_OK){
        fprintf(stderr, "==>  %s\n", curl_easy_strerror(r));
    }

    fclose(f);
    curl_easy_cleanup(curlhandle);
    curl_global_cleanup();

    return r == CURLE_OK;
}
#else //非阻塞型下载
bool curlDownloadFile(const std::string& remotepath,
                                      const std::string& localpath,
                                      ProgressData& progressdata,
                                      downloadProgressCallBack cb, /*progress callback function*/
                                      LoadType type,char* user_pwd,char *port,
                                      bool resume, long timeout , long tries )
{

    // 文件名包含中文会导致文件下载失败

    // printf("%s %d : %s  %s \n",__FUNCTION__,__LINE__,localpath,remotepath);
    std::cout << __FUNCTION__ <<__LINE__ << "    " << remotepath << "   " << localpath << std::endl;

    CURL *curlhandle = NULL;
    // curl_global_init(CURL_GLOBAL_ALL);
    CURLM *multi_handle;
    int still_running = 0; /* keep number of running handles */
    int repeats = 0;

    curl_global_init(CURL_GLOBAL_DEFAULT);

    curlhandle = curl_easy_init();
    if(!curlhandle){  return false; }

    multi_handle = curl_multi_init();
    if(!multi_handle){  return false; }

    /* add the individual transfers */
    curl_multi_add_handle(multi_handle, curlhandle);

    FILE *f;
    long filesize =0 ;
    CURLMcode r = CURLM_CALL_MULTI_PERFORM;

    struct myprogress prog;
    char *progress_data = (char*) &prog;
    long intiSize = 0;
    FILE *file = fopen(localpath.c_str(),"wb");
    if(!file){
        perror(" open failed.\n");
        return r;
    }

    intiSize = filelength(fileno(file));
    fclose(file);
    prog.local_file_len = intiSize;


    // if( prog.local_file_len > 0) resume  = 1;

    f = fopen(localpath.c_str(), "ab+");
    if ( NULL == f ) {
        perror(NULL);
        return false;
    }


    /// 解决传参中包含中文乱码的问题
    using namespace  TiangongCloud;
    QString remotePathQstring = str2qstr(remotepath);
    QStringList lst = remotePathQstring.split("/");
    lst.removeLast();
    QString rFileName = lst.last();
    QFileInfo info(remotePathQstring);
    QString _baseName = info.baseName();
    QString _surfix = info.suffix();

    qDebug() << __FUNCTION__ << __LINE__ << _baseName << _surfix;

    /// basename可能是中文,必须转码

    QString prePath = lst.join("/");
    string param;
    char * escape_control = curl_escape(_baseName.toStdString().c_str(), _baseName.length());
    param = string(escape_control);
    curl_free(escape_control);

    // %E8%BD%B4-PMI.par
    // %D6%E1-PM.par
    // string dlurl = qstr2str(prePath) + "/" + param + + "." + _surfix.toStdString() + rFileName.toStdString();
    // std::cout << __FUNCTION__ <<__LINE__ << "    " <<  dlurl << std::endl;

    // curl_easy_setopt(curlhandle, CURLOPT_URL, remotepath );
    UTool tool;
    curl_easy_setopt(curlhandle, CURLOPT_URL, string(string_To_UTF8(tool.urlcode(remotepath))).c_str()  );

    std::cout << "++++++++++++++++++ " << __FUNCTION__ << "   " << __LINE__ << "  "
              << remotepath << "    " << string_To_UTF8(tool.urlcode(remotepath)) << std::endl;

    if(timeout)
        curl_easy_setopt(curlhandle, CURLOPT_CONNECTTIMEOUT, timeout);
    curl_easy_setopt(curlhandle, CURLOPT_HEADERFUNCTION, &sdkcommucation::getcontentlengthfunc);
    curl_easy_setopt(curlhandle, CURLOPT_HEADERDATA, &filesize);
    curl_easy_setopt(curlhandle, CURLOPT_RESUME_FROM_LARGE, resume ? prog.local_file_len : 0);
    curl_easy_setopt(curlhandle, CURLOPT_WRITEDATA, f);
    curl_easy_setopt(curlhandle, CURLOPT_WRITEFUNCTION, &sdkcommucation::write_data);

    if(cb)
        curl_easy_setopt(curlhandle, CURLOPT_PROGRESSFUNCTION, cb);
    else
        curl_easy_setopt(curlhandle, CURLOPT_PROGRESSFUNCTION, defaultDownloadProgressFunc);

    curl_easy_setopt(curlhandle, CURLOPT_PROGRESSDATA, &progressdata);

    if(FTP == type){
        /* "name:password" to use when fetching. */
        curl_easy_setopt(curlhandle, CURLOPT_USERPWD, user_pwd);
        curl_easy_setopt(curlhandle, CURLOPT_FTPPORT,port ? port : "-");
        curl_easy_setopt(curlhandle, CURLOPT_FTP_CREATE_MISSING_DIRS, 0L);
    }

    curl_easy_setopt(curlhandle, CURLOPT_SSL_VERIFYPEER, 0);
    curl_easy_setopt(curlhandle, CURLOPT_SSL_VERIFYHOST, 0);
    curl_easy_setopt(curlhandle, CURLOPT_NOPROGRESS, 0L);
    curl_easy_setopt(curlhandle, CURLOPT_VERBOSE, 1L);

    /* we start some action by calling perform right away */
    r = curl_multi_perform(multi_handle, &still_running);

    while(still_running) {
      int numfds;

      /* wait for activity, timeout or "nothing" */
      r = curl_multi_wait(multi_handle, NULL, 0, 1000, &numfds);

      if(r != CURLM_OK) {
          r = CURLM_BAD_EASY_HANDLE;
        fprintf(stderr, "curl_multi_wait() failed, code %d.\n", r);
        break;
      }

      /* 'numfds' being zero means either a timeout or no file descriptors to
         wait for. Try timeout on first occurrence, then assume no file
         descriptors and no file descriptors to wait for means wait for 100
         milliseconds. */

      if(!numfds) {
        repeats++; /* count number of repeated zero numfds */
        if(repeats > 1) {
          WAITMS(100); /* sleep 100 milliseconds */
        }
      }
      else
        repeats = 0;

      if (repeats > 30)  //30s重连
      {
          r = CURLM_BAD_EASY_HANDLE;
          fprintf(stderr, "netwoek is error:%d", r);
          break;
      }

      r = curl_multi_perform(multi_handle, &still_running);
    }

    curl_multi_remove_handle(multi_handle, curlhandle);

    curl_easy_cleanup(curlhandle);

    curl_multi_cleanup(multi_handle);

    curl_global_cleanup();

    fclose(f);

    return r == CURLE_OK;
}
#endif
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

东方忘忧

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值