Search code examples
c++curlprogress-barcurlpp

Progress Indicator for Multiple downloads with cURLpp


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.


Solution

  • 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:

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