<分区>
大家好阅读这个话题,我的平台是win32。我在使用 libcurl 时遇到了问题。
我的目标是用 libcurl 编写一个下载程序,它包括请求一个 url 来下载一个文件,将文件保存在本地 (fwrite),在下载时显示进度条。
问题是它可以很好地下载非常小的文件,但是当请求更大的文件(如 30MB)时,它会在完成之前停止。
我怎样才能调试这个程序来处理任何大小的文件?
我不熟悉 libcurl,任何简单的细节都可能有所帮助。我能否回答 curl_easy 系列如何调用多个回调函数、两个回调函数中的任何一个的编码不当或 libcurl 缺少一些规则? 随时回答我任何问题。
我尝试过的事情:
1.我试过重新编译 libcurl 的版本。现在我正在使用使用“WITH_SSL=static”编译的 libcurl-7.64。
2.我试过很多网站,找到了线索:非常小的(比如80kb)文件的网站将下载完成并带有进度条。但较大的文件(如 30Mb)将不完整。我的猜测之一是由于文件较大,它因某些传输问题而停止。
代码:
static FILE * fp;
static size_t write_callback(char *ptr, size_t size, size_t nmemb, void *userdata)
{
size_t nWrite = fwrite(ptr, size, nmemb, fp);
return nWrite;
}
static int progress_callback(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow)
{
(void)ultotal;
(void)ulnow;
int totaldotz = 40;
double fractiondownloaded = (double)dlnow / (double)dltotal;
int dotz = (int)(fractiondownloaded * totaldotz);
printf("%3.0f%% [", fractiondownloaded * 100); //print the number percentage of the progress
int i = 0;
for (; i < dotz; i++) { //print "=" to show progress
printf("=");
}
for (; i < totaldotz; i++) { //print space to occupy the rest
printf(" ");
}
printf("]\r");
fflush(stdout);
return 0;
}
int download_function(CURL *curl,const char * url, const char * path)
{
curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, progress_callback);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
fopen_s(&fp, path, "ab+");
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 5L);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false);
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3L);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3L);
char * error = NULL;
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error);
CURLcode retcCode = curl_easy_perform(curl);
fclose(fp);
const char* pError = curl_easy_strerror(retcCode);
if (curl) {
curl_easy_cleanup(curl);
}
return 0;
}