如何在C++的libcurl中实现HTTPS中断下载的断点续传?
Implementing Resumable HTTPS Downloads with libcurl in C++
First off, let's clear up a common misconception: CURL_RESUME_FROM (and its big-file counterpart CURL_RESUME_FROM_LARGE) absolutely work with HTTPS—the issue usually comes down to server support for range requests or incorrect client-side implementation. Here's a practical breakdown of the APIs and code you need to make this work:
Key libcurl APIs for Resumable Downloads
CURLOPT_RESUME_FROM: Sets the byte offset to start downloading from. Use this for files smaller than 2GB (since it takes alongparameter).CURLOPT_RESUME_FROM_LARGE: For files larger than 2GB, use this instead—it accepts acurl_off_ttype to handle bigger offsets.CURLOPT_WRITEFUNCTION: A custom callback function that appends downloaded data to your local file (instead of overwriting it, which is default behavior).CURLOPT_WRITEDATA: Passes your open file pointer (in append mode) to the write callback so it knows where to write the data.
Step-by-Step Implementation
1. Check Local File Size
First, calculate how much of the file you've already downloaded to get your resume offset:
#include <fstream> #include <curl/curl.h> curl_off_t get_local_file_size(const std::string& filename) { std::ifstream file(filename, std::ios::binary | std::ios::ate); if (!file.is_open()) { return 0; // File doesn't exist, start from beginning } return static_cast<curl_off_t>(file.tellg()); }
2. Configure libcurl for Resumable Download
Set up the curl handle with resume options and append-mode file writing:
size_t write_callback(void* ptr, size_t size, size_t nmemb, FILE* stream) { return fwrite(ptr, size, nmemb, stream); } int resume_https_download(const std::string& url, const std::string& output_file) { CURL* curl = curl_easy_init(); if (!curl) { return 1; } curl_off_t resume_offset = get_local_file_size(output_file); FILE* fp = fopen(output_file.c_str(), resume_offset > 0 ? "ab" : "wb"); if (!fp) { curl_easy_cleanup(curl); return 1; } // Core HTTPS and download options curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); // Follow redirects if needed curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L); // Enable SSL verification (secure default) curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L); // Set resume offset if we have partial data if (resume_offset > 0) { curl_easy_setopt(curl, CURLOPT_RESUME_FROM_LARGE, resume_offset); } // Configure write behavior to append to file curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp); // Execute the download CURLcode res = curl_easy_perform(curl); // Verify if resume worked if (resume_offset > 0) { long response_code; curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); if (response_code == 206) { printf("Successfully resumed download from offset %lld\n", resume_offset); } else if (response_code == 200) { printf("Server doesn't support range requests—downloaded from start\n"); } } // Cleanup resources fclose(fp); curl_easy_cleanup(curl); return res == CURLE_OK ? 0 : 1; }
3. Usage Example
Call the function with your target HTTPS URL and output file path:
int main() { curl_global_init(CURL_GLOBAL_DEFAULT); int result = resume_https_download("https://speed.hetzner.de/100MB.bin", "sample1.bin"); curl_global_cleanup(); return result; }
Important Notes
- Server Support: The remote server must accept
RangeHTTP headers (most modern servers do, but it's not guaranteed). If the server doesn't support range requests, libcurl will fall back to downloading the entire file from the start. - Error Handling: Always check the return code of
curl_easy_perform—common errors include network issues, SSL verification failures, or file access problems. - Large Files: Stick with
CURLOPT_RESUME_FROM_LARGEfor files over 2GB, aslongcan't handle offsets that big on 32-bit systems.
内容的提问来源于stack exchange,提问作者Nikhil S
相关产品推荐
相关产品推荐

