Pergunta

I am writing a program that downloads multiple files (at the moment its only 2). I am trying to get it to display a progress bar for each download using the ProgressFunction callback. The problem I am running into is I cannot figure out a way to differentiate between the progress between the two files. Right now it is switching between the two. I have tried looking for any further documentation but it seems the API link is broken on their site and there is not much other than some basic examples.

    //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);

I am not entirely sure what part of my code would be relevant so here are the parts pertaining to the progress callback. Any help would be appreciated.

Foi útil?

Solução

Disclaimer: My C++ is rusty, and I have never used curlpp before, so the code below may need a bit of massaging.

What you need in your callback function is something that can differentiate between the two downloads. Since curlpp doesn't give you that, you probably need to use a functor instead. So, for your progress callback, make a class similar to:

Now, you should be able to use this like:

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

Of course, you will need to think about the lifetime of these callback functors. Probably leaving them on stack would be a bad idea.


EDIT: There seems to be an easier way to do this. in utilspp/functor.h, there are two template functions defined: make_functor() and BindFirst(). So you could simply add a downloadIndex parameter to your ProgressCallback:

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

And register as:

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

Outras dicas

Here some dirty scratch just to express the idea:

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
}

But you have to fix it before using (ownership stuff should be resolved, and vector's buffer reallocation will cause crash and so on) but I hope the idea is clear.

The core libcurl library allows you to pass user-defined data to a progress callback via the CURLOPT_PROGRESSDATA option, where the callback has an additional void *clientp parameter in front of the double dltotal parameter:

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

Looking at cURLpp's latest source code, it does not appear to expose access to the CURLOPT_PROGRESSDATA option, though.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top