c++ - 使用 libcurl 下载功能,但它不完整

标签 c++ c winapi libcurl

<分区>

大家好阅读这个话题,我的平台是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;

}

最佳答案

@ccxxshow 似乎是对的。设置超时选项给我 CURLE_OPERATION_TIMEDOUT 错误。

删除此行后,我可以成功下载大约 9MB 的 PDF 文件。

curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3L);

enter image description here

enter image description here

我的完整代码:

#include <curl/curl.h>

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;

}

int main()
{
    CURL *testCurl = NULL;
    const char *fileAddr = "https://gotocon.com/dl/goto-cph-2015/slides/AndersLybecker_and_SebastianBrandes_DevelopingIoTSolutionsWithWindows10AndAzure.pdf";
    download_function(testCurl, fileAddr, "my-9MB.pdf");
}

关于c++ - 使用 libcurl 下载功能,但它不完整,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55370084/

相关文章:

c++ - 使用结构的二维 vector

c++ - 移位操作后使用进位标志

c++ - 除以余数时,奇数是否总是返回 floor?

c++ - "const LPVOID"等于 "void * const"吗?

c++ - 通过分析汇编列表验证 gcc/g++ 中的编译器优化

c - 在 C 中打印二维 map

在 strcpy 上崩溃,不知道为什么?

c - 大数组的全局声明如何在 C 中工作?

javascript - 在 js-ctypes 中调用 SCardListReaders 时出错

c++ - WinApi LineTo 不刷新行