Einfacher C++ HTTP-Download mit libcurl Easy API

Problem

Mit der libcurl Easy API möchtest du eine Datei über HTTP GET herunterladen. Es sollen keine erweiterten Features wie Authentifizierung verwendet werden.

Das Download-Ergebnis soll in einem std::string gespeichert werden.

Lösung

Du kannst diese einfache Wrapper-Klasse verwenden:

Header:

HTTPDownloader.hpp
/**
 * HTTPDownloader.hpp
 *
 * Ein einfacher C++-Wrapper für die libcurl Easy API.
 *
 * Geschrieben von Uli Köhler (techoverflow.net)
 * Veröffentlicht unter CC0 1.0 Universal (public domain)
 */
#ifndef HTTPDOWNLOADER_HPP
#define HTTPDOWNLOADER_HPP

#include <string>

/**
 * Ein nicht-thread-sicherer einfacher HTTP-Downloader basierend auf libcURL-easy
 */
class HTTPDownloader {
public:
    HTTPDownloader();
    ~HTTPDownloader();
    /**
     * Lädt eine Datei über HTTP GET herunter und speichert sie in einem std::string
     * @param url Die URL zum Herunterladen
     * @return Das Download-Ergebnis
     */
    std::string download(const std::string& url);
private:
    void* curl;
};

#endif  /* HTTPDOWNLOADER_HPP */

Quellcode:

HTTPDownloader.cpp
/**
 * HTTPDownloader.cpp
 *
 * Ein einfacher C++-Wrapper für die libcurl Easy API.
 *
 * Geschrieben von Uli Köhler (techoverflow.net)
 * Veröffentlicht unter CC0 1.0 Universal (public domain)
 */
#include "HTTPDownloader.hpp"
#include <curl/curl.h>
#include <curl/easy.h>
#include <curl/curlbuild.h>
#include <sstream>
#include <iostream>
using namespace std;

size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream) {
    string data((const char*) ptr, (size_t) size * nmemb);
    *((stringstream*) stream) << data << endl;
    return size * nmemb;
}

HTTPDownloader::HTTPDownloader() {
    curl = curl_easy_init();
}

HTTPDownloader::~HTTPDownloader() {
    curl_easy_cleanup(curl);
}

string HTTPDownloader::download(const std::string& url) {
    curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
    /* example.com wird weitergeleitet, also sagen wir libcurl, Weiterleitungen zu folgen */
    curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
    curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); //Verhindert den "longjmp causes uninitialized stack frame" Bug
    curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "deflate");
    std::stringstream out;
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &out);
    /* Anfrage ausführen, res erhält den Rückgabecode */
    CURLcode res = curl_easy_perform(curl);
    /* Auf Fehler prüfen */
    if (res != CURLE_OK) {
        fprintf(stderr, "curl_easy_perform() failed: %s\n",
                curl_easy_strerror(res));
    }
    return out.str();
}

Beispielverwendungscode:

HTTPDownloaderExample.cpp
/**
 * HTTPDownloaderExample.cpp
 *
 * Ein einfacher C++-Wrapper für die libcurl Easy API.
 * Diese Datei enthält Beispielcode zur Verwendung der HTTPDownloader-Klasse.
 *
 * Kompilieren wie folgt: g++ -o HTTPDownloaderExample HTTPDownloaderExample.cpp HTTPDownloader.cpp -lcurl
 *
 * Geschrieben von Uli Köhler (techoverflow.net)
 * Veröffentlicht unter CC0 1.0 Universal (public domain)
 */
#include "HTTPDownloader.hpp"
#include <iostream>
#include <string>

int main(int argc, char** argv) {
    HTTPDownloader downloader;
    std::string content = downloader.download("https://stackoverflow.com");
    std::cout << content << std::endl;
}

Check out similar posts by category: C/C++, Networking