You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用libcurl下载:如何预检查字节范围支持及获取Accept-Ranges头?

libcurl断点续传:预先检查服务器范围请求支持的方案

你遇到的核心问题是:用CURLOPT_RANGE做断点续传时,若服务器不支持范围请求会返回完整文件,导致本地文件追加后体积过大。下面提供两种可靠的检查方案,以及获取Accept-Ranges字段的具体实现:

一、通过HEAD请求解析响应头判断支持性

libcurl没有直接提供获取Accept-Ranges的内置宏,必须通过自定义头回调函数解析响应头。步骤如下:

  1. 发送HEAD请求(仅获取响应头,不下载内容)
  2. 在回调函数中匹配Accept-Ranges字段,判断其值是否为bytes

代码示例

#include <curl/curl.h>
#include <string.h>
#include <stdio.h>

// 自定义头回调:提取Accept-Ranges字段
size_t parse_header(char *buffer, size_t size, size_t nitems, void *userdata) {
    size_t len = size * nitems;
    char *range_header = strstr(buffer, "Accept-Ranges: ");
    if (range_header) {
        // 截取字段值,去除换行符
        char *value = range_header + strlen("Accept-Ranges: ");
        value[strcspn(value, "\r\n")] = '\0';
        // 标记是否支持字节范围请求
        *(int*)userdata = (strcmp(value, "bytes") == 0) ? 1 : 0;
    }
    return len;
}

int main() {
    CURL *curl = curl_easy_init();
    if (!curl) return 1;

    int supports_range = 0;
    const char *url = "你的下载URL";

    // 配置HEAD请求
    curl_easy_setopt(curl, CURLOPT_URL, url);
    curl_easy_setopt(curl, CURLOPT_NOBODY, 1L); // 只取响应头
    curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, parse_header);
    curl_easy_setopt(curl, CURLOPT_HEADERDATA, &supports_range);

    // 执行请求
    CURLcode res = curl_easy_perform(curl);
    if (res == CURLE_OK) {
        if (supports_range) {
            printf("服务器支持字节范围请求\n");
            // 此处执行断点续传逻辑:获取本地文件大小,设置CURLOPT_RANGE
        } else {
            printf("服务器不支持范围请求,需重新下载完整文件\n");
        }
    }

    curl_easy_cleanup(curl);
    return 0;
}

二、通过小范围请求验证(更可靠)

部分服务器可能对HEAD请求的响应与GET不一致,此时直接发送一个极小范围的请求(比如请求第0个字节),通过响应码判断:

  • 响应码为206 Partial Content:支持范围请求
  • 响应码为200 OK:不支持范围请求,会返回完整文件

代码示例

CURL *curl = curl_easy_init();
if (!curl) return 1;

const char *url = "你的下载URL";
long resp_code = 0;

// 请求0-0范围的字节
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_RANGE, "0-0");
curl_easy_setopt(curl, CURLOPT_NOBODY, 1L); // 可选:只取响应头,避免下载1字节

CURLcode res = curl_easy_perform(curl);
if (res == CURLE_OK) {
    curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &resp_code);
    if (resp_code == 206) {
        printf("服务器支持范围请求\n");
        // 执行断点续传
    } else if (resp_code == 200) {
        printf("服务器不支持范围请求\n");
        // 删除本地不完整文件,重新下载
    }
}

curl_easy_cleanup(curl);

断点续传的安全逻辑

确认服务器支持范围请求后,再执行续传:

  1. 获取本地已下载文件的大小(用stat或fseek+ftell)
  2. 设置CURLOPT_RANGE为[已下载字节数]-(例如本地已下1024字节,设为1024-)
  3. 打开本地文件时使用追加模式(fopen(file, "ab"))或定位到文件末尾写入(fseek(fp, 0, SEEK_END))

如果服务器不支持范围请求,务必删除本地不完整文件后重新下载,避免追加完整文件导致体积翻倍。

内容的提问来源于stack exchange,提问作者TWitvliet

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 18:36:25