Индикатор прогресса для нескольких загрузок с cURLpp - PullRequest
4 голосов
/ 13 октября 2011

Я пишу программу, которая загружает несколько файлов (на данный момент ее всего 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 ]

2 голосов
/ 13 октября 2011

Вот какая-то грязная царапина, просто чтобы выразить идею:

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
}

Но вы должны исправить это перед использованием (вещи владельца должны быть решены, а перераспределение буфера вектора вызовет сбой и т. Д.), Но я надеюсь, что идея ясна.

1 голос
/ 13 октября 2011

Отказ от ответственности: Мой 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));
0 голосов
/ 13 октября 2011

Базовая библиотека libcurl позволяет передавать пользовательские данные в обратный вызов хода выполнения с помощью параметра CURLOPT_PROGRESSDATA, где обратный вызов имеет дополнительный параметр void *clientp перед параметром double dltotal:

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

Глядя на последний исходный код cURLpp, он не предоставляет доступ к опции CURLOPT_PROGRESSDATA.

...