#include "httpclient.h" #include #include #include #include #include #include #include #include #include class HttpClientPrivate { public: HttpClientPrivate(const QString& url); QString url; QUrlQuery params; QHash headers; QNetworkAccessManager* manager; bool debug; enum HttpMethod { GET, POST, PUT, DELETE }; static QNetworkAccessManager* getManager(HttpClientPrivate* d, bool* internal); static QNetworkRequest createRequest(HttpClientPrivate* d, HttpMethod method); static void get(HttpClientPrivate* d, HttpMethod method, std::function successHandler, std::function errorHandler, const char* encoding); static QString readReply(QNetworkReply* reply, const char* encoding = "UTF-8"); static void handleFinish(bool debug, const QString& successMessage, const QString& errorMessage, std::function successHandler, std::function errorHandler, QNetworkReply* reply, QNetworkAccessManager* manager); }; HttpClientPrivate::HttpClientPrivate(const QString& url) : url(url), manager(NULL), debug(false) {} HttpClient::HttpClient(const QString& url) : d(new HttpClientPrivate(url)) {} HttpClient::~HttpClient() { delete d; } HttpClient& HttpClient::manager(QNetworkAccessManager* manager) { d->manager = manager; return *this; } HttpClient& HttpClient::debug(bool debug) { d->debug = debug; return *this; } HttpClient& HttpClient::param(const QString& name, const QString& value) { d->params.addQueryItem(name, value); return *this; } HttpClient& HttpClient::header(const QString& header, const QString& value) { d->headers[header] = value; return *this; } void HttpClient::get(std::function successHandler, std::function errorHandler, const char* encoding) { HttpClientPrivate::get(d, HttpClientPrivate::GET, successHandler, errorHandler, encoding); } void HttpClient::download( const QString& savePath, std::function successHandler, std::function errorHandler, std::function progressHandler) { bool debug = d->debug; QFile* file = new QFile(savePath); if (file->open(QIODevice::WriteOnly)) { download( [=](const QByteArray& data) { file->write(data); }, [=](const QString&) { file->flush(); file->close(); file->deleteLater(); if (debug) { qDebug().noquote() << QString("download finished, save to: %1").arg(savePath); } if (NULL != successHandler) { successHandler( QString("download finished, save to: %1").arg(savePath)); } }, errorHandler, progressHandler); } else { if (debug) { qDebug().noquote() << QString("open file error: %1").arg(savePath); } if (NULL != errorHandler) { errorHandler(QString("open file error: %1").arg(savePath)); } } } void HttpClient::download( std::function readyRead, std::function successHandler, std::function errorHandler, std::function progressHandler) { bool debug = d->debug; bool internal; QNetworkAccessManager* manager = HttpClientPrivate::getManager(d, &internal); QNetworkRequest request = HttpClientPrivate::createRequest(d, HttpClientPrivate::GET); QNetworkReply* reply = manager->get(request); QObject::connect(reply, &QNetworkReply::readyRead, [=] { readyRead(reply->readAll()); }); QObject::connect(reply, &QNetworkReply::finished, [=] { QString successMessage = "download finished"; QString errorMessage = reply->errorString(); HttpClientPrivate::handleFinish(debug, successMessage, errorMessage, successHandler, errorHandler, reply, internal ? manager : NULL); }); QObject::connect(reply, &QNetworkReply::downloadProgress, [=](qint64 bytesReceived, qint64 bytesTotal) { if (NULL != progressHandler) { progressHandler(bytesReceived, bytesTotal); } }); } void HttpClientPrivate::get(HttpClientPrivate* d, HttpMethod method, std::function successHandler, std::function errorHandler, const char* encoding) { bool internal; QNetworkAccessManager* manager = HttpClientPrivate::getManager(d, &internal); QNetworkRequest request = HttpClientPrivate::createRequest(d, HttpClientPrivate::GET); QNetworkReply* reply = NULL; switch (method) { case HttpClientPrivate::GET: reply = manager->get(request); break; default: break; } QObject::connect(reply, &QNetworkReply::finished, [=] { QString successMessage = HttpClientPrivate::readReply(reply, encoding); QString errorMessage = reply->errorString(); HttpClientPrivate::handleFinish(d->debug, successMessage, errorMessage, successHandler, errorHandler, reply, internal ? manager : NULL); }); } QNetworkAccessManager* HttpClientPrivate::getManager(HttpClientPrivate* d, bool* internal) { *internal = d->manager == NULL; return *internal ? new QNetworkAccessManager() : d->manager; } QNetworkRequest HttpClientPrivate::createRequest(HttpClientPrivate* d, HttpMethod method) { if (!d->params.isEmpty()) { d->url += "?" + d->params.toString(QUrl::FullyEncoded); } if (d->debug) { qDebug().noquote() << "url:" << d->url; QList > paramItems = d->params.queryItems(); for (int i = 0; i < paramItems.size(); ++i) { QString name = paramItems.at(i).first; QString value = paramItems.at(i).second; if (0 == i) { qDebug().noquote() << QString("params: %1=%2").arg(name).arg(value); } else { qDebug().noquote() << QString(" %1=%2").arg(name).arg(value); } } } QNetworkRequest request(QUrl(d->url)); QHashIterator iter(d->headers); while (iter.hasNext()) { iter.next(); request.setRawHeader(iter.key().toUtf8(), iter.value().toUtf8()); } return request; } QString HttpClientPrivate::readReply(QNetworkReply* reply, const char* encoding) { QTextStream in(reply); QString result; in.setCodec(encoding); while (!in.atEnd()) { result += in.readLine(); } return result; } void HttpClientPrivate::handleFinish( bool debug, const QString& successMessage, const QString& errorMessage, std::function successHandler, std::function errorHandler, QNetworkReply* reply, QNetworkAccessManager* manager) { if (reply->error() == QNetworkReply::NoError) { if (debug) { qDebug().noquote() << QString("request successed: %1").arg(successMessage); } if (NULL != successHandler) { successHandler(successMessage); } } else { if (debug) { qDebug().noquote() << QString("request failed: %1").arg(errorMessage); } if (NULL != errorHandler) { errorHandler(errorMessage); } } reply->deleteLater(); if (NULL != manager) { manager->deleteLater(); } }