使用cURLpp进行多个下载的进度指示器

8

我正在编写一个程序,用于下载多个文件(目前只有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);

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

3个回答

5

这里只是简单的示意草稿:

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
}

但是在使用之前,您必须修复它(所有权问题应该得到解决,向量的缓冲区重新分配会导致崩溃等),但我希望这个想法是清楚的。


3

免责声明:本人对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()。因此,你可以简单地向你的ProgressCallback添加一个downloadIndex参数。
double ProgressCallBack(int dlIdx,
                        double dltotal, double dlnow,
                        double ultotal, double ulnow);

并注册为:

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

0
核心的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选项的方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接