如何使用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"> ...
解决步骤
使用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移除多余请求头
Content-Type: application/json是POST请求发送JSON数据时用的,GET请求下载文件不需要这个头,直接删除该行:// 删掉此行 // slist = curl_slist_append(slist, "Content-Type: application/json");检查Token权限
确保你的Personal Access Token(PAT)拥有repo权限,生成Token时必须勾选repo选项,否则无法访问私有仓库。同时确认Token未过期、未被撤销。启用调试定位问题
打开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
相关产品推荐
相关产品推荐

