libcurl响应头缺失Content-Length 命令行可获取但接口返回-1问题
问题原因
你的代码存在两个核心错误,直接导致无法正常获取Content-Length:
- 回调函数返回值不符合libcurl规范
你自定义的头回调hcb和写回调wcb都固定返回0,但libcurl明确要求这两个回调必须返回实际成功处理的字节总数,也就是传入的size * nmemb的计算结果。返回0会被libcurl判定为传输发生致命错误,立刻中断整个HTTP响应接收流程,所以你只能拿到第一行HTTP/2 200状态行,后续的Content-Length等所有响应头还没来得及接收就被终止,自然读不到对应字段。 curl_easy_getinfo参数类型不匹配
你用CURLINFO_CONTENT_LENGTH_DOWNLOAD_T选项获取下载长度时,传入的是int类型变量的指针,但这个选项要求接收参数必须是curl_off_t(64位宽整型)类型的指针,类型不匹配会触发未定义行为,哪怕传输正常也可能读到错误的内存值,拿不到正确长度。
修正方案
- 把两个回调的返回值改成正确的已处理字节数,哪怕不需要处理响应头/响应体内容,也必须返回正确的字节数,不能返回0
- 把存储ContentLength的变量类型改成
curl_off_t,打印时使用对应格式符 - 增加基础错误检查,确认
curl_easy_perform返回值为CURLE_OK后再读取响应信息,避免传输失败时读取无效值
修正后的可运行代码:
#include <stdlib.h> #include <stdio.h> #include <curl/curl.h> int hcb(void *contents, size_t size, size_t nmemb, void *data) { size_t total = size * nmemb; printf("%.*s\n", (int)total, (char *)contents); return total; // 返回实际处理的字节数 } int wcb(void *contents, size_t size, size_t nmemb, void *data) { // 不需要处理响应体也必须返回正确字节数,否则会中断传输 return size * nmemb; } ssize_t myfunc(){ char url[] = "http://thisisafakeurl.com/test.txt"; CURL *c = curl_easy_init(); if(c) { CURLcode res; curl_off_t ContentLength = -1; // 使用接口要求的curl_off_t类型 curl_easy_setopt(c, CURLOPT_URL, url); curl_easy_setopt(c, CURLOPT_HEADERFUNCTION, hcb); curl_easy_setopt(c, CURLOPT_WRITEFUNCTION, wcb); res = curl_easy_perform(c); if (res == CURLE_OK) { // 先判断请求是否执行成功 curl_easy_getinfo(c, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T, &ContentLength); printf("content length: %lld\n", (long long)ContentLength); } else { printf("curl request failed: %s\n", curl_easy_strerror(res)); } curl_easy_cleanup(c); } return 0; } int main() { myfunc(); return 0; }
补充说明:如果服务端使用HTTP/2时开启了分块传输编码,本身就不会返回Content-Length字段,这种情况下接口返回-1是符合预期的,但你当前遇到的问题是回调返回错误导致传输提前中断,和分块传输场景无关。
内容的提问来源于stack exchange,提问作者Solver
相关产品推荐
相关产品推荐

