C++ libcurl console progress bar

后端 未结 3 1034
攒了一身酷
攒了一身酷 2020-12-14 23:32

I would like a progress bar to appear in the console window while a file is being downloaded. My code is this: Download file using libcurl in C/C++.

How to have a p

相关标签:
3条回答
  • 2020-12-14 23:49

    Like apt progress bar

    #include <iostream>
    #include <fstream>
    #include <include/curl/curl.h>//Or #include <curl/curl.h>
    #include <windows.h>
    #include <math.h>
    
    using namespace std;
    
    int nb_bar;
    double last_progress, progress_bar_adv;
    
    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
    
    int progress_bar (void *bar, double t, double d)
    {
        if(last_progress != round(d/t*100))
        {
          nb_bar = 25;
          progress_bar_adv = round(d/t*nb_bar);
    
          cout<<"\r ";
          SetConsoleTextAttribute(hConsole, 160);
          cout<<" Progress : [ ";
    
          if(round(d/t*100) < 10)
          { cout<<"0"<<round(d/t*100)<<" %]"; }
          else
          { cout<<round(d/t*100)<<" %] "; }
    
          SetConsoleTextAttribute(hConsole, 15);
          cout<<" [";
          SetConsoleTextAttribute(hConsole, 10);
          for(int i = 0 ; i <= progress_bar_adv ; i++)
          { cout<<"#"; }
          SetConsoleTextAttribute(hConsole, 15);
          for(int i = 0 ; i < nb_bar - progress_bar_adv; i++)
          { cout<<"."; }
    
          cout<<"]";
          last_progress = round(d/t*100);
        }
      return 0;
    }
    
    
    int main()
    {
      CURL *curl_download;
      FILE *fp;
      CURLcode res;
      string url = "http://www.gecif.net/articles/mathematiques/pi/pi_1_million.txt", output_file = "pi.txt";
    
      curl_download = curl_easy_init();
    
      if (curl_download)
      {
          //SetConsoleTextAttribute(hConsole, 11);
          fp = fopen(output_file.c_str(),"wb");
    
          curl_easy_setopt(curl_download, CURLOPT_URL, url.c_str());
          curl_easy_setopt(curl_download, CURLOPT_WRITEFUNCTION, NULL);
          curl_easy_setopt(curl_download, CURLOPT_WRITEDATA, fp);
          curl_easy_setopt(curl_download, CURLOPT_NOPROGRESS, FALSE);
          //progress_bar : the fonction for the progress bar
          curl_easy_setopt(curl_download, CURLOPT_PROGRESSFUNCTION, progress_bar);
    
          //Text color :   SetConsoleTextAttribute(hConsole, nb_color);
          SetConsoleTextAttribute(hConsole, 11);
          cout<<" Start download"<<endl<<endl;
    
          res = curl_easy_perform(curl_download);
    
          fclose(fp);
          if(res == CURLE_OK)
          {
            SetConsoleTextAttribute(hConsole, 10);
            cout<<endl<<endl<<" The file was download with succes"<<endl;
          }
          else
          {
            SetConsoleTextAttribute(hConsole, 4);
            cout<<endl<<endl<<" Error"<<endl;
          }
          curl_easy_cleanup(curl_download);
      }
      SetConsoleTextAttribute(hConsole, 11);
      return 0;
    }
    
    0 讨论(0)
  • 2020-12-14 23:50

    From the curl documentation

    CURLOPT_PROGRESSFUNCTION

    Function pointer that should match the curl_progress_callback prototype found in . This function gets called by libcurl instead of its internal equivalent with a frequent interval during operation (roughly once per second) no matter if data is being transfered or not. Unknown/unused argument values passed to the callback will be set to zero (like if you only download data, the upload size will remain 0). Returning a non-zero value from this callback will cause libcurl to abort the transfer and return CURLE_ABORTED_BY_CALLBACK.

    So:

    You provide a function that looks like this

    int progress_func(void* ptr, double TotalToDownload, double NowDownloaded, double TotalToUpload, double NowUploaded)
    {
        // It's here you will write the code for the progress message or bar
    }
    

    And some extra options after the existing options

    curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);  // already there
    // Internal CURL progressmeter must be disabled if we provide our own callback
    curl_easy_setopt(curl, CURLOPT_NOPROGRESS, FALSE);
    // Install the callback function
    curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progress_func); 
    

    That's all that needs to be done

    0 讨论(0)
  • 2020-12-14 23:55

    Your meter.

    #include <math.h>
    
    int progress_func(void* ptr, double TotalToDownload, double NowDownloaded, 
                        double TotalToUpload, double NowUploaded)
    {
        // ensure that the file to be downloaded is not empty
        // because that would cause a division by zero error later on
        if (TotalToDownload <= 0.0)) {
            return 0;
        }
    
        // how wide you want the progress meter to be
        int totaldotz=40;
        double fractiondownloaded = NowDownloaded / TotalToDownload;
        // part of the progressmeter that's already "full"
        int dotz = (int) round(fractiondownloaded * totaldotz);
    
        // create the "meter"
        int ii=0;
        printf("%3.0f%% [",fractiondownloaded*100);
        // part  that's full already
        for ( ; ii < dotz;ii++) {
            printf("=");
        }
        // remaining part (spaces)
        for ( ; ii < totaldotz;ii++) {
            printf(" ");
        }
        // and back to line begin - do not forget the fflush to avoid output buffering problems!
        printf("]\r");
        fflush(stdout);
        // if you don't return 0, the transfer will be aborted - see the documentation
        return 0; 
    }
    
    0 讨论(0)
提交回复
热议问题