最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++使用libcurl輕松實(shí)現(xiàn)文件下載

 更新時(shí)間:2025年08月21日 08:34:44   作者:xiaokang-coding  
這篇文章將用最簡單的方式,帶大家掌握C++ + libcurl實(shí)現(xiàn)文件下載的核心技術(shù),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下

最近很多同學(xué)在后臺問我:"康哥,想用C++實(shí)現(xiàn)文件下載功能,但不知道從哪里入手,網(wǎng)上的教程要么太簡單,要么太復(fù)雜,有沒有適合新手的實(shí)戰(zhàn)教程?"

今天就來滿足大家的需求!用最簡單的方式,帶你掌握C++ + libcurl實(shí)現(xiàn)文件下載的核心技術(shù)。

不僅讓你學(xué)會(huì)基礎(chǔ)下載,更重要的是為后續(xù)的多線程高性能下載器打下堅(jiān)實(shí)基礎(chǔ)!

為什么選擇libcurl?

在C++中實(shí)現(xiàn)HTTP下載,我們有很多選擇:

  • socket編程:太底層,需要手動(dòng)處理HTTP協(xié)議
  • 第三方網(wǎng)絡(luò)庫:學(xué)習(xí)成本高,依賴復(fù)雜
  • libcurl:工業(yè)級標(biāo)準(zhǔn),簡單易用,幾乎所有Linux系統(tǒng)都預(yù)裝

libcurl的優(yōu)勢:

  • 久經(jīng)考驗(yàn): 被Git用于HTTP操作,被PHP內(nèi)置cURL擴(kuò)展采用
  • 功能強(qiáng)大:支持HTTP/HTTPS/FTP等20+協(xié)議
  • 文檔完善:官方文檔詳細(xì),社區(qū)活躍
  • 性能優(yōu)秀:C語言實(shí)現(xiàn),效率極高
  • 跨平臺:Windows/Linux/macOS全支持

環(huán)境準(zhǔn)備

Ubuntu/Debian系統(tǒng)

sudo apt-get update
sudo apt-get install libcurl4-openssl-dev

CentOS/RHEL系統(tǒng)

sudo yum install libcurl-devel
# 或者新版本使用
sudo dnf install libcurl-devel

驗(yàn)證安裝

curl-config --version

如果顯示版本號,說明安裝成功!

第一個(gè)下載程序:HelloDownloader

我們從最簡單的例子開始。創(chuàng)建文件 hello_downloader.cpp

#include <iostream>
#include <fstream>
#include <curl/curl.h>

// 數(shù)據(jù)寫入回調(diào)函數(shù)
size_t writeData(void* ptr, size_t size, size_t nmemb, FILE* stream) {
    size_t written = fwrite(ptr, size, nmemb, stream);
    return written;
}

int main() {
    CURL* curl;
    FILE* fp;
    CURLcode res;
    
    // 下載鏈接(這是一個(gè)測試文件)
    const char* url = "https://httpbin.org/json";
    const char* outfilename = "test.json";
    
    // 全局初始化curl
    curl_global_init(CURL_GLOBAL_DEFAULT);
    
    // 創(chuàng)建curl句柄
    curl = curl_easy_init();
    if(curl) {
        // 打開本地文件準(zhǔn)備寫入
        fp = fopen(outfilename, "wb");
        if(!fp) {
            std::cerr << "無法創(chuàng)建文件!" << std::endl;
            curl_easy_cleanup(curl);
            curl_global_cleanup();
            return 1;
        }
        
        // 設(shè)置URL
        curl_easy_setopt(curl, CURLOPT_URL, url);
        
        // 設(shè)置寫入回調(diào)函數(shù)
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeData);
        
        // 設(shè)置寫入文件指針
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
        
        // 跟隨重定向
        curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
        
        // 執(zhí)行下載
        res = curl_easy_perform(curl);
        
        // 檢查結(jié)果
        if(res != CURLE_OK) {
            std::cerr << "下載失敗: " << curl_easy_strerror(res) << std::endl;
        } else {
            std::cout << "下載成功!文件保存為: " << outfilename << std::endl;
        }
        
        // 清理
        fclose(fp);
        curl_easy_cleanup(curl);
    }
    
    curl_global_cleanup();
    return 0;
}

編譯運(yùn)行:

g++ -o hello_downloader hello_downloader.cpp -lcurl
./hello_downloader

如果一切正常,你會(huì)看到:

下載成功!文件保存為: test.json

恭喜!你的第一個(gè)C++下載器誕生了!

進(jìn)階版本:帶進(jìn)度顯示的下載器

基礎(chǔ)版本太樸素?來個(gè)炫酷的進(jìn)度條版本!

#include <iostream>
#include <fstream>
#include <iomanip>
#include <curl/curl.h>

// 進(jìn)度回調(diào)函數(shù)
int progressCallback(void* ptr, double totalToDownload, double nowDownloaded, 
                    double totalToUpload, double nowUploaded) {
    if (totalToDownload <= 0.0) return 0;
    
    double percentage = (nowDownloaded / totalToDownload) * 100.0;
    int barWidth = 50;
    int pos = static_cast<int>(barWidth * percentage / 100.0);
    
    std::cout << "\r[";
    for (int i = 0; i < barWidth; ++i) {
        if (i < pos) std::cout << "=";
        else if (i == pos) std::cout << ">";
        else std::cout << " ";
    }
    std::cout << "] " << std::fixed << std::setprecision(1) << percentage << "%";
    std::cout << " (" << static_cast<long>(nowDownloaded) << "/" 
              << static_cast<long>(totalToDownload) << " bytes)";
    std::cout.flush();
    
    return 0;
}

// 寫入數(shù)據(jù)回調(diào)
size_t writeData(void* ptr, size_t size, size_t nmemb, FILE* stream) {
    return fwrite(ptr, size, nmemb, stream);
}

class SimpleDownloader {
private:
    CURL* curl;
    
public:
    SimpleDownloader() {
        curl_global_init(CURL_GLOBAL_DEFAULT);
        curl = curl_easy_init();
    }
    
    ~SimpleDownloader() {
        if (curl) {
            curl_easy_cleanup(curl);
        }
        curl_global_cleanup();
    }
    
    bool download(const std::string& url, const std::string& filename) {
        if (!curl) return false;
        
        FILE* fp = fopen(filename.c_str(), "wb");
        if (!fp) {
            std::cerr << "無法創(chuàng)建文件: " << filename << std::endl;
            return false;
        }
        
        // 基本設(shè)置
        curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeData);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
        curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
        
        // 進(jìn)度顯示設(shè)置
        curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
        curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progressCallback);
        
        // 用戶代理(有些網(wǎng)站需要)
        curl_easy_setopt(curl, CURLOPT_USERAGENT, "SimpleDownloader/1.0");
        
        // 超時(shí)設(shè)置
        curl_easy_setopt(curl, CURLOPT_TIMEOUT, 300L);  // 5分鐘超時(shí)
        curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30L);  // 連接30秒超時(shí)
        
        std::cout << "開始下載: " << url << std::endl;
        CURLcode res = curl_easy_perform(curl);
        std::cout << std::endl;  // 換行
        
        fclose(fp);
        
        if (res != CURLE_OK) {
            std::cerr << "下載失敗: " << curl_easy_strerror(res) << std::endl;
            return false;
        }
        
        std::cout << "下載完成!文件保存為: " << filename << std::endl;
        return true;
    }
};

int main() {
    SimpleDownloader downloader;
    
    // 你可以替換成任何你想下載的文件
    std::string url = "https://httpbin.org/json";
    std::string filename = "downloaded_file.json";
    
    if (downloader.download(url, filename)) {
        std::cout << "下載成功!" << std::endl;
    } else {
        std::cout << "下載失敗!" << std::endl;
    }
    
    return 0;
}

編譯運(yùn)行:

g++ -o progress_downloader progress_downloader.cpp -lcurl
./progress_downloader

你會(huì)看到類似這樣的效果:

開始下載: https://httpbin.org/json
[==================================================] 100.0% (429/429 bytes)

核心概念詳解

1. CURL句柄管理

// 全局初始化(程序啟動(dòng)時(shí)調(diào)用一次)
curl_global_init(CURL_GLOBAL_DEFAULT);

// 創(chuàng)建會(huì)話句柄
CURL* curl = curl_easy_init();

// 使用完畢后清理
curl_easy_cleanup(curl);
curl_global_cleanup();

2. 關(guān)鍵選項(xiàng)設(shè)置

// 基礎(chǔ)設(shè)置
curl_easy_setopt(curl, CURLOPT_URL, url);                    // 設(shè)置URL
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);          // 跟隨重定向
curl_easy_setopt(curl, CURLOPT_USERAGENT, "MyApp/1.0");      // 用戶代理

// 超時(shí)控制
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 300L);               // 總超時(shí)時(shí)間
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30L);         // 連接超時(shí)

// SSL設(shè)置(HTTPS需要)
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);          // 驗(yàn)證證書
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L);          // 驗(yàn)證主機(jī)名

3. 回調(diào)函數(shù)機(jī)制

libcurl通過回調(diào)函數(shù)處理數(shù)據(jù):

// 數(shù)據(jù)接收回調(diào)
size_t writeCallback(void* contents, size_t size, size_t nmemb, void* userp) {
    size_t realsize = size * nmemb;
    // 處理接收到的數(shù)據(jù)
    return realsize;  // 返回處理的字節(jié)數(shù)
}

// 進(jìn)度回調(diào)
int progressCallback(void* clientp, double dltotal, double dlnow, 
                    double ultotal, double ulnow) {
    // 顯示進(jìn)度信息
    return 0;  // 返回0繼續(xù),非0中止
}

常見問題與解決方案

問題1:編譯時(shí)找不到curl.h

解決方案:

# 檢查是否安裝開發(fā)包
dpkg -l | grep curl
# 如果沒有,重新安裝
sudo apt-get install libcurl4-openssl-dev

問題2:下載HTTPS鏈接失敗

解決方案:

// 添加SSL設(shè)置
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L);
curl_easy_setopt(curl, CURLOPT_CAINFO, "/etc/ssl/certs/ca-certificates.crt");

問題3:某些網(wǎng)站返回403錯(cuò)誤

解決方案:

// 設(shè)置更真實(shí)的用戶代理
curl_easy_setopt(curl, CURLOPT_USERAGENT, 
    "Mozilla/5.0 (Linux; x86_64) AppleWebKit/537.36");

// 添加請求頭
struct curl_slist* headers = NULL;
headers = curl_slist_append(headers, "Accept: */*");
headers = curl_slist_append(headers, "Accept-Encoding: gzip, deflate");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);

性能優(yōu)化小貼士

1. 啟用壓縮

curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "");  // 自動(dòng)處理所有支持的編碼

2. 復(fù)用連接

curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);
curl_easy_setopt(curl, CURLOPT_TCP_KEEPIDLE, 120L);
curl_easy_setopt(curl, CURLOPT_TCP_KEEPINTVL, 60L);

3. 設(shè)置合適的緩沖區(qū)

curl_easy_setopt(curl, CURLOPT_BUFFERSIZE, 102400L);  // 100KB緩沖區(qū)

總結(jié)

通過這篇教程,我們學(xué)會(huì)了:

  • libcurl環(huán)境搭建:快速安裝和配置
  • 基礎(chǔ)下載實(shí)現(xiàn):從最簡單的 demo 開始
  • 進(jìn)階功能添加:進(jìn)度顯示、錯(cuò)誤處理、超時(shí)控制
  • 面向?qū)ο蠓庋b:用類封裝提高代碼復(fù)用性
  • 常見問題解決:實(shí)際開發(fā)中的坑點(diǎn)和解決方案

現(xiàn)在你已經(jīng)掌握了C++單線程下載的核心技術(shù)!

但是,單線程下載在面對大文件時(shí)還是太慢了。試想一下:

  • 下載幾GB的文件需要等很久
  • 網(wǎng)絡(luò)中斷后又要重新開始
  • ....

如果能實(shí)現(xiàn)多線程并發(fā)下載,速度提升10倍以上,那該多爽!

到此這篇關(guān)于C++使用libcurl輕松實(shí)現(xiàn)文件下載的文章就介紹到這了,更多相關(guān)C++ libcurl文件下載內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++實(shí)現(xiàn)求動(dòng)態(tài)矩陣各元素的和

    C++實(shí)現(xiàn)求動(dòng)態(tài)矩陣各元素的和

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)求動(dòng)態(tài)矩陣各元素的和,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • 帶你了解C++的數(shù)組與函數(shù)

    帶你了解C++的數(shù)組與函數(shù)

    這篇文章主要介紹了C++的數(shù)組與函數(shù),包括數(shù)組的初始化等基本知識,需要的朋友可以參考下,希望能給你帶來幫助
    2021-08-08
  • 使用C++實(shí)現(xiàn)鏈表元素的反轉(zhuǎn)

    使用C++實(shí)現(xiàn)鏈表元素的反轉(zhuǎn)

    反轉(zhuǎn)鏈表是鏈表操作中一個(gè)經(jīng)典的問題,也是面試中常見的考題,本文將從思路到實(shí)現(xiàn)一步步地講解如何實(shí)現(xiàn)鏈表的反轉(zhuǎn),幫助初學(xué)者理解這一操作,我們將使用C++代碼演示具體實(shí)現(xiàn),同時(shí)分析時(shí)間復(fù)雜度和空間復(fù)雜度,需要的朋友可以參考下
    2025-02-02
  • C語言中g(shù)etchar的用法以及實(shí)例解析

    C語言中g(shù)etchar的用法以及實(shí)例解析

    getchar()是stdio.h中的庫函數(shù),它的作用是從stdin流中讀入一個(gè)字符,下面這篇文章主要給大家介紹了關(guān)于C語言中g(shù)etchar的用法以及實(shí)例的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-03-03
  • 從C語言中讀取Python 類文件對象

    從C語言中讀取Python 類文件對象

    這篇文章主要介紹了如何從C語言中讀取Python 類文件對象,文中講解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-07-07
  • 關(guān)于C++STL string類的介紹及模擬實(shí)現(xiàn)

    關(guān)于C++STL string類的介紹及模擬實(shí)現(xiàn)

    這篇文章主要介紹了關(guān)于C++STL string類的介紹及模擬實(shí)現(xiàn)的相關(guān)資料,需要的朋友可以參考下面具體的文章內(nèi)容
    2021-09-09
  • C語言使用矩形法求定積分的通用函數(shù)

    C語言使用矩形法求定積分的通用函數(shù)

    這篇文章主要為大家詳細(xì)介紹了C語言使用矩形法求定積分的通用函數(shù),分別求解sinx, cosx,e^x,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-02-02
  • 用C語言舉例講解數(shù)據(jù)結(jié)構(gòu)中的算法復(fù)雜度結(jié)與順序表

    用C語言舉例講解數(shù)據(jù)結(jié)構(gòu)中的算法復(fù)雜度結(jié)與順序表

    這篇文章主要介紹了講解數(shù)據(jù)結(jié)構(gòu)中的算法復(fù)雜度結(jié)與順序表的C語言版示例,包括對時(shí)間復(fù)雜度和空間復(fù)雜度等概念的簡單講解,需要的朋友可以參考下
    2016-02-02
  • Qt使用QPainter實(shí)現(xiàn)自定義圓形進(jìn)度條

    Qt使用QPainter實(shí)現(xiàn)自定義圓形進(jìn)度條

    這篇文章主要介紹了Qt如何使用QPainter實(shí)現(xiàn)自定義圓形進(jìn)度條功能,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)Qt有一定的幫助,需要的可以參考一下
    2022-06-06
  • Qt中QSettings配置文件的讀寫和應(yīng)用場景詳解

    Qt中QSettings配置文件的讀寫和應(yīng)用場景詳解

    這篇文章主要給大家介紹了關(guān)于Qt中QSettings配置文件的讀寫和應(yīng)用場景的相關(guān)資料,QSettings能讀寫配置文件,當(dāng)配置文件不存在時(shí),可生成配置文件,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-10-10

最新評論

长武县| 临桂县| 屏东县| 舟山市| 华阴市| 如东县| 营口市| 茌平县| 茌平县| 崇仁县| 嘉祥县| 泾阳县| 定南县| 集贤县| 集贤县| 叶城县| 安康市| 防城港市| 镶黄旗| 翼城县| 徐州市| 建德市| 桃园市| 高台县| 仙桃市| 富裕县| 巩义市| 宜黄县| 钦州市| 云浮市| 成都市| 镇坪县| 离岛区| 苍梧县| 宁海县| 寻乌县| 扎赉特旗| 高淳县| 马公市| 福泉市| 宜君县|