libcurl中CURLOPT_WRITEFUNCTION设置回调函数

本文介绍如何使用libcurl库正确地下载并保存整个文件。通过分析一个错误示例,指出在接收数据过程中不当关闭文件导致数据丢失的问题,并提供修正后的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

文档:

Let’s assume for a while that you want to receive data as the URL identifies a remote resource you want to get here. Since you write a sort of application that needs this transfer, I assume that you would like to get the data passed to you directly instead of simply getting it passed to stdout. So, you write your own function that matches this prototype:
size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp);
You tell libcurl to pass all data to this function by issuing a function similar to this:
curl_easy_setopt(easyhandle, CURLOPT_WRITEFUNCTION, write_data);



文档只是简单的说
你可以通过设置 curl_easy_setopt(easyhandle, CURLOPT_WRITEFUNCTION, write_data)这个函数来告诉libcurl,传递所有的数据到上面的 size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp);这个自己定义的满足这个格式的函数就行了。
BUT,我们来看一个例子:

#include <iostream>
#include <curl/curl.h>
using namespace std;

size_t receive_data(void *buffer, size_t size, size_t nmemb, FILE *file);
int main(){
    char url[] = "http://www.sina.com.cn";
    char path[] = "save_file.txt";
    FILE *file = fopen(path,"w");
    curl_global_init(CURL_GLOBAL_ALL);
    CURL *handle = curl_easy_init();
    curl_easy_setopt(handle, CURLOPT_URL, url);
    curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, receive_data);
    curl_easy_setopt(handle, CURLOPT_WRITEDATA, file);
    cout << curl_easy_perform(handle);


    curl_easy_cleanup(handle);
    curl_global_cleanup();

    return 0;
}

size_t receive_data(void *buffer, size_t size, size_t nmemb, FILE *file){
    size_t r_size = fwrite(buffer, size, nmemb, file);
    fclose(file);
    return r_size;
}

:)是不是觉得完全没有任何问题对不对,我下载了sina的html,然后保存到save_file.txt里。
BUT,当我打开save_file.txt发现里面只有不全的一段html,并没有全部在里面。为什么呢?
因为curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, receive_data);这个设置的回调函数的调用是在每次socket接收到数据之后,并不是socket接收了所有的数据,然后才调用设定的回调函数
当socket才接收到一部分数据的时候,就调用了回调函数。回调函数将接收到的不完全数据保存到文件里,然后关闭文件。然后socket又接收到了下一部分的数据,调用回调函数。但是此时文件已经被关闭了,程序出错,所以后续的内容不能够被保存到文件中。所以看到的文件也就是不完整的。

修改后的代码:
#include <iostream>
#include <curl/curl.h>
using namespace std;

size_t receive_data(void *buffer, size_t size, size_t nmemb, FILE *file);

int main() {
    char url[] = "http://www.sina.com.cn";
    char path[] = "save_file.txt";
    FILE *file = fopen(path, "w");
    curl_global_init(CURL_GLOBAL_ALL);
    CURL *handle = curl_easy_init();
    curl_easy_setopt(handle, CURLOPT_URL, url);
    curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, receive_data);
    curl_easy_setopt(handle, CURLOPT_WRITEDATA, file);
    cout << curl_easy_perform(handle);

    fclose(file);
    curl_easy_cleanup(handle);
    curl_global_cleanup();
    return 0;
}

size_t receive_data(void *buffer, size_t size, size_t nmemb, FILE *file) {
    size_t r_size = fwrite(buffer, size, nmemb, file);
    return r_size;
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值