I'm using C/C++ in Linux Environment to practicing and trying to download file from the internet, then print percent downloaded while downloading file.
I determine 2 main steps for this problem.
- Get the file size before download.
- Get number of bytes downloaded.
I solved 2. by lib cURL, but stuck in 1: I tried cURL with CURLOPT_XFERINFOFUNCTION option but it doesn't work for file .deb. In addition, it print data in file that I can't control it. I don't know where was the mistake. And if we can't solve it by cURL please tell me what should I use instead for number 1.
here's what I've done:
#include <stdio.h>
#include <curl/curl.h>
#define STOP_DOWNLOAD_AFTER_THIS_MANY_BYTES 6000
FILE *fp = fopen("file.txt", "w");
struct myprogress {
curl_off_t lastruntime; /* type depends on version, see above */
CURL *curl;
};
/* this is how the CURLOPT_XFERINFOFUNCTION callback works */
static int xferinfo(void *p,
curl_off_t dltotal, curl_off_t dlnow,
curl_off_t ultotal, curl_off_t ulnow)
{
struct myprogress *myp = (struct myprogress *)p;
CURL *curl = myp->curl;
curl_off_t curtime = 0;
curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME_T, &curtime);
/* under certain circumstances it may be desirable for certain functionality
to only run every N seconds, in order to do this the transaction time can
be used */
if((curtime - myp->lastruntime) >= MINIMAL_PROGRESS_FUNCTIONALITY_INTERVAL) {
myp->lastruntime = curtime;
fprintf(fp, "TOTAL TIME: %lu.%06lu\n",
(unsigned long)(curtime / 1000000),
(unsigned long)(curtime % 1000000));
}
fprintf(fp, "UP: %lu of %lu DOWN: %lu of %lu\n",
(unsigned long)ulnow, (unsigned long)ultotal,
(unsigned long)dlnow, (unsigned long)dltotal);
if(dlnow >= dltotal)
return 1;
return 0;
}
int main(void)
{
CURL *curl;
CURLcode res = CURLE_OK;
struct myprogress prog;
curl = curl_easy_init();
if(curl) {
prog.lastruntime = 0;
prog.curl = curl;
curl_easy_setopt(curl, CURLOPT_URL, "https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb");
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, xferinfo);
/* pass the struct pointer into the xferinfo function */
curl_easy_setopt(curl, CURLOPT_XFERINFODATA, &prog);
// curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
// curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
res = curl_easy_perform(curl);
if(res != CURLE_OK){
printf("Fail\n");
// fprintf(stderr, "%s\n", curl_easy_strerror(res));
}
/* always cleanup */
curl_easy_cleanup(curl);
}
fclose(fp);
return (int)res;
}
To run it: g++ -o runfile main.cpp -lcurl && ./runfile