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

如何使用curl从私有GitHub仓库下载文件?

解决C++ curl从私有GitHub仓库下载文件返回HTML的问题

问题现象

用C++ curl代码从私有GitHub仓库下载文件时,得到的不是目标文件内容,而是GitHub的HTML页面。尝试了Authorization: token和Authorization: Bearer两种授权头格式,均未解决问题。

原代码

#include <curl/curl.h>

static size_t WriteMemoryCallback(void* contents, size_t size, size_t nmemb, void* userp) {
    size_t realsize = size * nmemb;
    auto& mem = *static_cast<std::string*>(userp);
    mem.append(static_cast<char*>(contents), realsize);
    return realsize;
}

void Download(std::string& data, char* url)
{
    CURL* curl_handle;
    CURLcode res;
    struct curl_slist* slist{};

    curl_handle = curl_easy_init();

    curl_easy_setopt(curl_handle, CURLOPT_URL, url);
    SecureZeroMemory(url, strlen(url));        

    slist = curl_slist_append(slist, "Authorization: token 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");
    slist = curl_slist_append(slist, "Content-Type: application/json");
    curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, slist);

    curl_easy_setopt(curl_handle, CURLOPT_TCP_KEEPALIVE, 0);
    curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
    curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, &data);
    curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
    curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1L);  // redirects
   
    //curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 1L); // only to debug

    res = curl_easy_perform(curl_handle);

    if(res != CURLE_OK)
       std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << '\n';

    curl_easy_cleanup(curl_handle);
    curl_global_cleanup();
}

int main(int argc, char* argv[]) {
     std::string data;
     Download(data, /* link */);
}

错误返回内容

<!DOCTYPE html>
<html lang="en" data-color-mode="auto" data-light-theme="light" data-dark-theme="dark" data-a11y-animated-images="system">
  <head>
    <meta charset="utf-8">
  <link rel="dns-prefetch" href="https://github.githubassets.com">
  <link rel="dns-prefetch" href="https://avatars.githubusercontent.com">
  <link rel="dns-prefetch" href="https://github-cloud.s3.amazonaws.com">
  <link rel="dns-prefetch" href="https://user-images.githubusercontent.com/">
  <link rel="preconnect" href="https://github.githubassets.com" crossorigin>
  <link rel="preconnect" href="https://avatars.githubusercontent.com">
...

解决步骤

  1. 使用GitHub API专用URL
    不要用浏览器里的网页URL,改用GitHub Contents API的格式:

    https://api.github.com/repos/{用户名}/{仓库名}/contents/{文件路径}
    

    例如下载username/private-repo仓库里的src/main.cpp,URL应为:

    https://api.github.com/repos/username/private-repo/contents/src/main.cpp
    
  2. 移除多余请求头
    Content-Type: application/json是POST请求发送JSON数据时用的,GET请求下载文件不需要这个头,直接删除该行:

    // 删掉此行
    // slist = curl_slist_append(slist, "Content-Type: application/json");
    
  3. 检查Token权限
    确保你的Personal Access Token(PAT)拥有repo权限,生成Token时必须勾选repo选项,否则无法访问私有仓库。同时确认Token未过期、未被撤销。

  4. 启用调试定位问题
    打开CURLOPT_VERBOSE选项,查看请求的详细日志(包括HTTP状态码、重定向地址等),方便快速定位问题:

    curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 1L);
    

修正后的代码片段

void Download(std::string& data, char* url)
{
    CURL* curl_handle;
    CURLcode res;
    struct curl_slist* slist{};

    curl_handle = curl_easy_init();

    curl_easy_setopt(curl_handle, CURLOPT_URL, url);
    SecureZeroMemory(url, strlen(url));        

    // 仅保留正确的授权头
    slist = curl_slist_append(slist, "Authorization: token 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");
    curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, slist);

    curl_easy_setopt(curl_handle, CURLOPT_TCP_KEEPALIVE, 0);
    curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
    curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, &data);
    curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
    curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1L);
    curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 1L); // 启用调试日志

    res = curl_easy_perform(curl_handle);

    if(res != CURLE_OK)
       std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << '\n';

    // 新增:清理请求头链表,避免内存泄漏
    curl_slist_free_all(slist);
    curl_easy_cleanup(curl_handle);
    curl_global_cleanup();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 22:30:49