【问题标题】:Progress Indicator for Multiple downloads with cURLpp使用 cURLpp 进行多次下载的进度指示器
【发布时间】:2011-12-06 11:50:21
【问题描述】:

我正在编写一个下载多个文件的程序(目前只有 2 个)。我试图让它使用ProgressFunction 回调显示每次下载的进度条。我遇到的问题是我无法找出区分两个文件之间进度的方法。现在它正在两者之间切换。我已经尝试寻找任何进一步的文档,但似乎 API 链接在他们的网站上已损坏,除了一些基本示例之外没有太多其他内容。

    //ProgressCalback
    double ProgressCallBack(double dltotal, double dlnow, double ultotal, double ulnow){
       double progress = (dlnow/dltotal) * 100;
       std::ostringstream strs;
       float percent = floorf(progress * 100) / 100;
       strs << percent;
       printf("%s\t%d\t%d\t%d\t%d\n", strs.str().c_str(),dltotal, dlnow, ultotal, ulnow);
       return 0;
    };

    curlpp::options::ProgressFunction progressBar(ProgressCallBack);
    request1.setOpt(new curlpp::options::Url(url1));
    request1.setOpt(new curlpp::options::Verbose(false));
    request1.setOpt(new curlpp::options::NoProgress(0));
    request1.setOpt(progressBar);

我不完全确定我的代码的哪一部分是相关的,所以这里是与进度回调有关的部分。任何帮助将不胜感激。

【问题讨论】:

    标签: c++ curl progress-bar curlpp


    【解决方案1】:

    这里有些肮脏的划痕只是为了表达这个想法:

    class CurlppProgress
    {
      class Entry 
      {
      public:
        Entry( const CurlppProgress *owner );
    
        const CurlppProgress *owner;
        double dlTotal, dlNow, ulTotal, ulNow;
    
        void callback( double dltotal, double dlnow, double ultotal, double ulnow );
      };
      std::vector<Entry> entries;
    
      void print_progress() const;
      friend class Entry;
    public:
      CurlppProgress();
    
      void AddEntry( curlpp::Easy *request );
    };
    
    CurlppProgress::Entry::Entry( const CurlppProgress *_owner )
      : owner( _owner )
      , dlNow()
      , dlTotal()
      , ulNow()
      , ulTotal()
    {
    }
    
    void CurlppProgress::Entry::callback( double _dltotal, double _dlnow, double _ultotal, double _ulnow )
    {
      dlNow = _dlnow;
      dlTotal = _dltotal;
      ulNow = _ulnow;
      ulTotal = _ultotal;
      owner->print_progress();
    }
    
    void CurlppProgress::AddEntry( curlpp::Easy *request )
    {
      Entry newEntry( this );
      m_entries.push_back( newEntry );
      curlpp::types::ProgressFunctionFunctor progressFunctor(&m_entries.back(), &CurlppProgress::Entry::callback);
      request->setOpt(new curlpp::options::ProgressFunction(progressFunctor));
    
    }
    
    void CurlppProgress::print_progress() const
    {
      double ulnow = 0.0;
      double ultotal = 0.0;
      double dlnow = 0.0;
      double dltotal = 0.0;
      for ( std::vector<Entry>::const_iterator i = entries.begin(), e = entries.end(); i != e; ++i )
      {
        ulnow += i->ulNow;
        ulTotal += i->ulTotal;
        dlnow += i->dlNow;
        dltotal += i->dlTotal;
      }
    
      // print progress here
    }
    

    但是你必须在使用之前修复它(所有权问题应该解决,并且vector的缓冲区重新分配会导致崩溃等)但我希望这个想法是明确的。

    【讨论】:

      【解决方案2】:

      免责声明:我的 C++ 生锈了,而且我之前从未使用过 curlpp,所以下面的代码可能需要稍微按摩一下。

      您需要在回调函数中区分两种下载。由于 curlpp 没有给你,你可能需要使用仿函数。因此,对于您的进度回调,请创建一个类似于以下内容的类:

      class ProgressCallback
      {
      public:
          ProgressCallback(int index) : downloadIndex(downloadIndex)
          {
          }
      
          double operator()(double dltotal, double dlnow, double ultotal, double ulnow)
          {
             double progress = (dlnow/dltotal) * 100;
             std::ostringstream strs;
             float percent = floorf(progress * 100) / 100;
             strs << percent;
             printf("%d: %s\t%d\t%d\t%d\t%d\n", downloadIndex,
                    strs.str().c_str(),dltotal, dlnow, ultotal, ulnow);
             return 0;
          }
      
      private:
          int downloadIndex;
      };
      

      现在,您应该可以像这样使用它了:

      ProgressCallback callback1(1);
      curlpp::options::ProgressFunction progressBar(callback1);
      

      当然,您需要考虑这些回调函子的生命周期。可能将它们留在堆栈上是个坏主意。


      编辑:似乎有一种更简单的方法可以做到这一点。在utilspp/functor.h 中,定义了两个模板函数:make_functor() 和 BindFirst()。因此,您可以简单地将downloadIndex 参数添加到您的ProgressCallback

      double ProgressCallBack(int dlIdx,
                              double dltotal, double dlnow,
                              double ultotal, double ulnow);
      

      并注册为:

      curlpp::options::ProgressFunction
          progressBar(BindFirst(make_functor(ProgressCallback), 1));
      

      【讨论】:

        【解决方案3】:

        核心 libcurl 库允许您通过 CURLOPT_PROGRESSDATA 选项将用户定义的数据传递给进度回调,其中回调在 double dltotal 参数前面有一个额外的 void *clientp 参数:

        typedef int (*curl_progress_callback)(void *clientp,
                                              double dltotal,
                                              double dlnow,
                                              double ultotal,
                                              double ulnow);
        

        查看 cURLpp 的最新源代码,但它似乎没有公开对 CURLOPT_PROGRESSDATA 选项的访问权限。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-04-27
          • 1970-01-01
          • 1970-01-01
          • 2014-03-05
          • 1970-01-01
          • 2021-02-17
          • 1970-01-01
          • 2015-06-24
          相关资源
          最近更新 更多