Progress bar for multiple downloads using cURLpp

I am writing a program that downloads several files (currently it is only 2). I am trying to get it to display a progress bar for each download using the ProgressFunction callback. The problem I am facing is that I cannot figure out a way to distinguish between these two files. Now he is switching between them. I tried looking for any additional documentation, but the API link seems to be broken on their site and there is nothing but 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'm not quite sure which part of my code will make a difference, so here are the parts related to the reverse process. Any help would be appreciated.

+4
source share
3 answers

Disclaimer: my C ++ is rusty and I have never used curlpp before, so the code below may need to be massaged a little.

What you need in your callback function is that it can distinguish between two downloads. Since curlpp does not give you this, you will most likely need to use a functor. So, for your progress callback, create a class that looks like:

 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; }; 

Now you can use this as:

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

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


EDIT: There seems to be an easier way to do this. utilspp/functor.h defines two template functions: make_functor () and BindFirst (). Therefore, you can simply add the 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)); 
+1
source

Here are some dirty scratches 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 (you need to preserve ownership, and transferring the vector buffer will crash, etc.), but I hope the idea is clear.

+2
source

The main libcurl library allows you to transfer user data to the progress callback via the CURLOPT_PROGRESSDATA option, where the callback has an additional parameter void *clientp before the double dltotal parameter:

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

Looking at the cURLpp source code, however, it does not show access to the CURLOPT_PROGRESSDATA option.

0
source

All Articles