【问题标题】:Download file using libcurl in C/C++在 C/C++ 中使用 libcurl 下载文件
【发布时间】:2010-12-10 19:35:06
【问题描述】:

我正在构建一个应用程序(在使用 Dev-C++ 的 Windows 上),我希望它下载一个文件。我正在使用 libcurl 执行此操作(我已经使用 packman 安装了源代码)。我找到了一个工作示例 (http://siddhantahuja.wordpress.com/2009/04/12/how-to-download-a-file-from-a-url-and-save-onto-local-directory-in-c-using-libcurl/),但下载完成后它不会关闭文件。我希望有人举例说明如何用 c 或 c++ 下载文件。提前致谢!

【问题讨论】:

    标签: c file curl download libcurl


    【解决方案1】:

    您使用的示例是错误的。请参阅easy_setopt 的手册页。在示例中 write_data 使用它自己的 FILE,*outfile,而不是在 CURLOPT_WRITEDATA 中指定的 fp。这就是关闭 fp 会导致问题的原因 - 它甚至没有打开。

    这或多或少应该是这个样子(这里没有可供测试的 libcurl)

    #include <stdio.h>
    #include <curl/curl.h>
    /* For older cURL versions you will also need 
    #include <curl/types.h>
    #include <curl/easy.h>
    */
    #include <string>
    
    size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream) {
        size_t written = fwrite(ptr, size, nmemb, stream);
        return written;
    }
    
    int main(void) {
        CURL *curl;
        FILE *fp;
        CURLcode res;
        char *url = "http://localhost/aaa.txt";
        char outfilename[FILENAME_MAX] = "C:\\bbb.txt";
        curl = curl_easy_init();
        if (curl) {
            fp = fopen(outfilename,"wb");
            curl_easy_setopt(curl, CURLOPT_URL, url);
            curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
            curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
            res = curl_easy_perform(curl);
            /* always cleanup */
            curl_easy_cleanup(curl);
            fclose(fp);
        }
        return 0;
    }
    

    更新:正如@rsethc 建议的那样,types.heasy.h 不再出现在当前的 cURL 版本中。

    【讨论】:

    • 我试过这个(在 OSX 下),但我得到:警告:不推荐从字符串常量转换为 'char*' 未定义符号:“___gxx_personality_v0”,引用自:ccHRyU1T.o write_data 中的 _main( void*, unsigned long, unsigned long, __sFILE*)in ccHRyU1T.o ccHRyU1T.o ld 中的 CIE:找不到符号 collect2:ld 返回 1 个退出状态 请帮助!!
    • @TCB13 我写的程序是 C,而不是 C++。重新编译为 C,问题应该都消失了。
    • Libcurl 有自己的内部函数,用于将数据写入文件,其功能与上述write_data 相同。不需要写write_data 也不需要设置CURLOPT_WRITEFUNCTION。只需设置 CURLOPT_WRITEDATA 并保持 CURLOPT_WRITEFUNCTION 不变 - 您将获得相同的功能。
    • 在我的电脑上我不得不取出#include &lt;string&gt;。我尝试编译为 C 和 C++。在这两个示例上都立即返回并且文件为空白
    • wireshark 检查显示页面返回一个 302 永久移动,然后你得到一个 0 字节的输出。调用像 pudim.com.br 这样返回 200 个作品的网站。
    【解决方案2】:

    对于那些感兴趣的人,您可以通过传递 NULL 作为最后一个参数来避免编写自定义函数(如果您不打算对返回的数据进行额外处理)。
    在这种情况下,使用默认的内部函数。

    详情
    http://curl.haxx.se/libcurl/c/curl_easy_setopt.html#CURLOPTWRITEDATA

    例子

    #include <stdio.h>
    #include <curl/curl.h>
    
    int main(void)
    {
        CURL *curl;
        FILE *fp;
        CURLcode res;
        char *url = "http://stackoverflow.com";
        char outfilename[FILENAME_MAX] = "page.html";
        curl = curl_easy_init();                                                                                                                                                                                                                                                           
        if (curl)
        {   
            fp = fopen(outfilename,"wb");
            curl_easy_setopt(curl, CURLOPT_URL, url);
            curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, NULL);
            curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
            res = curl_easy_perform(curl);
            curl_easy_cleanup(curl);
            fclose(fp);
        }   
        return 0;
    }
    

    【讨论】:

    • 这在 Windows 上不起作用。在 Windows 上,您必须将 CURLOPT_WRITEFUNCTION 设置为非空,否则会发生崩溃。见curl.haxx.se/libcurl/c/CURLOPT_WRITEDATA.html
    • @PhilRosenberg 这听起来很不幸,因为这里curl.haxx.se/libcurl/c/CURLOPT_WRITEFUNCTION.html#DESCRIPTION 明确指出:“将此选项设置为 NULL 以获取使用的内部默认函数而不是您的回调。”所以这个“如果你使用 libcurl 作为 win32 DLL,如果您设置此选项,则必须使用 CURLOPT_WRITEFUNCTION,否则您将遇到崩溃。”应该没有效果,因为应该再次使用内部函数。
    • 这个例子立即返回,我得到一个空白文件
    • wireshark 检查显示页面返回一个 302 永久移动,然后你得到一个 0 字节的输出。调用像 pudim.com.br 这样返回 200 个作品的网站。
    • @GuerlandoOCs,与示例没有直接关系,对于重定向支持,您应该使用curl.se/libcurl/c/CURLOPT_FOLLOWLOCATION.html
    猜你喜欢
    • 2011-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多