Einfacher C++ HTTP-Download mit libcurl Easy API

English Deutsch

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