詳解Qt如何使用QtWebApp搭建Http服務(wù)器
一、QtWebApp源碼下載
a 、下載地址
http://www.stefanfrings.de/qtwebapp/QtWebApp.zip
b、 源碼目錄
二、http服務(wù)器搭建
a、使用qt creater新建一個(gè)項(xiàng)目
b、將QtWebApp的源碼拷貝到工程中
c、新建一個(gè)httpServer的類,繼承stefanfrings::HttpRequestHandler
需要包含相關(guān)頭文件
#include <QObject> #include "httpserver/httprequesthandler.h" #include <QSettings> #include "httpserver/httplistener.h" //新增代碼 #include "httpserver/httprequesthandler.h" //新增代碼 #include "httpserver/staticfilecontroller.h" #include "httpserver.h" #include <QFile> #include <QFileInfo>
httpServer.h
#ifndef HTTPSERVER_H #define HTTPSERVER_H #include <QObject> #include "httpserver/httprequesthandler.h" #include <QSettings> #include "httpserver/httplistener.h" //新增代碼 #include "httpserver/httprequesthandler.h" //新增代碼 #include "httpserver/staticfilecontroller.h" #include "httpserver.h" #include <QFile> #include <QFileInfo> class HttpServer : public stefanfrings::HttpRequestHandler { Q_OBJECT public: explicit HttpServer(QObject *parent = nullptr); void service(stefanfrings::HttpRequest& request, stefanfrings::HttpResponse& response); /** Encoding of text files */ QString encoding; /** Root directory of documents */ QString docroot; /** Maximum age of files in the browser cache */ int maxAge; struct CacheEntry { QByteArray document; qint64 created; QByteArray filename; }; /** Timeout for each cached file */ int cacheTimeout; /** Maximum size of files in cache, larger files are not cached */ int maxCachedFileSize; /** Cache storage */ QCache<QString,CacheEntry> cache; /** Used to synchronize cache access for threads */ QMutex mutex; }; #endif // HTTPSERVER_H
httpServer.cpp
#include "httpserver.h" HttpServer::HttpServer(QObject *parent) : HttpRequestHandler{parent} { QString configFileName=":/new/prefix1/webapp.ini"; QSettings* listenerSettings=new QSettings(configFileName, QSettings::IniFormat, this); listenerSettings->beginGroup("listener"); //新增代碼 new stefanfrings::HttpListener(listenerSettings, this, this); //新增代碼 docroot = "E:/Qt/learning/httpServer/HttpServer"; } void HttpServer::service(stefanfrings::HttpRequest &request, stefanfrings::HttpResponse &response) { QByteArray path=request.getPath(); // Check if we have the file in cache qint64 now=QDateTime::currentMSecsSinceEpoch(); mutex.lock(); CacheEntry* entry=cache.object(path); if (entry && (cacheTimeout==0 || entry->created>now-cacheTimeout)) { QByteArray document=entry->document; //copy the cached document, because other threads may destroy the cached entry immediately after mutex unlock. QByteArray filename=entry->filename; mutex.unlock(); qDebug("StaticFileController: Cache hit for %s",path.data()); response.setHeader("Content-Type", "application/x-zip-compressed"); response.setHeader("Cache-Control","max-age="+QByteArray::number(maxAge/1000)); response.write(document,true); } else { mutex.unlock(); // The file is not in cache. qDebug("StaticFileController: Cache miss for %s",path.data()); // Forbid access to files outside the docroot directory if (path.contains("/..")) { qWarning("StaticFileController: detected forbidden characters in path %s",path.data()); response.setStatus(403,"forbidden"); response.write("403 forbidden",true); return; } // If the filename is a directory, append index.html. if (QFileInfo(docroot+path).isDir()) { response.setStatus(404,"not found"); response.write("404 not found",true); return; } // Try to open the file QFile file(docroot+path); qDebug("StaticFileController: Open file %s",qPrintable(file.fileName())); if (file.open(QIODevice::ReadOnly)) { response.setHeader("Content-Type", "application/x-zip-compressed"); response.setHeader("Cache-Control","max-age="+QByteArray::number(maxAge/1000)); response.setHeader("Content-Length",QByteArray::number(file.size())); if (file.size()<=maxCachedFileSize) { // Return the file content and store it also in the cache entry=new CacheEntry(); while (!file.atEnd() && !file.error()) { QByteArray buffer=file.read(65536); response.write(buffer); entry->document.append(buffer); } entry->created=now; entry->filename=path; mutex.lock(); cache.insert(request.getPath(),entry,entry->document.size()); mutex.unlock(); } else { // Return the file content, do not store in cache while (!file.atEnd() && !file.error()) { response.write(file.read(65536)); } } file.close(); } else { if (file.exists()) { qWarning("StaticFileController: Cannot open existing file %s for reading",qPrintable(file.fileName())); response.setStatus(403,"forbidden"); response.write("403 forbidden",true); } else { response.setStatus(404,"not found"); response.write("404 not found",true); } } } }
程序中
QString configFileName=":/new/prefix1/webapp.ini"; QSettings* listenerSettings=new QSettings(configFileName, QSettings::IniFormat, this); listenerSettings->beginGroup("listener"); //新增代碼 new stefanfrings::HttpListener(listenerSettings, this, this); //新增代碼 docroot = "E:/Qt/learning/httpServer/HttpServer";
configFileName為配置文件內(nèi)容如下:
[listener] ;host=127.0.0.1 port=8080 minThreads=4 maxThreads=100 cleanupInterval=60000 readTimeout=60000 maxRequestSize=16000 maxMultiPartSize=10000000 [docroot] path=E:/Qt/learning/httpServer/HttpServer encoding=UTF-8 maxAge=60000 cacheTime=60000 cacheSize=1000000 maxCachedFileSize=65536
docroot 為文件的根目錄
三、啟動(dòng)http服務(wù)器
在mainwindow中新建一個(gè)HttpServer 變量,然后實(shí)例化,
此時(shí)http服務(wù)器已經(jīng)啟動(dòng)了。
四、獲取http服務(wù)器文件
a、打開瀏覽器輸入http://localhost:8080/filename
就能下載到文件名為filename的文件了。
b、我的程序中只實(shí)現(xiàn)了zip文件,如果是其他類型文件需要修改一下地方
為
void StaticFileController::setContentType(const QString fileName, HttpResponse &response) const { if (fileName.endsWith(".png")) { response.setHeader("Content-Type", "image/png"); } else if (fileName.endsWith(".jpg")) { response.setHeader("Content-Type", "image/jpeg"); } else if (fileName.endsWith(".gif")) { response.setHeader("Content-Type", "image/gif"); } else if (fileName.endsWith(".pdf")) { response.setHeader("Content-Type", "application/pdf"); } else if (fileName.endsWith(".txt")) { response.setHeader("Content-Type", qPrintable("text/plain; charset="+encoding)); } else if (fileName.endsWith(".html") || fileName.endsWith(".htm")) { response.setHeader("Content-Type", qPrintable("text/html; charset="+encoding)); } else if (fileName.endsWith(".css")) { response.setHeader("Content-Type", "text/css"); } else if (fileName.endsWith(".js")) { response.setHeader("Content-Type", "text/javascript"); } else if (fileName.endsWith(".svg")) { response.setHeader("Content-Type", "image/svg+xml"); } else if (fileName.endsWith(".woff")) { response.setHeader("Content-Type", "font/woff"); } else if (fileName.endsWith(".woff2")) { response.setHeader("Content-Type", "font/woff2"); } else if (fileName.endsWith(".ttf")) { response.setHeader("Content-Type", "application/x-font-ttf"); } else if (fileName.endsWith(".eot")) { response.setHeader("Content-Type", "application/vnd.ms-fontobject"); } else if (fileName.endsWith(".otf")) { response.setHeader("Content-Type", "application/font-otf"); } else if (fileName.endsWith(".json")) { response.setHeader("Content-Type", "application/json"); } else if (fileName.endsWith(".xml")) { response.setHeader("Content-Type", "text/xml"); } // Todo: add all of your content types else { qDebug("StaticFileController: unknown MIME type for filename '%s'", qPrintable(fileName)); } }
c、下載的源碼中有官方的例程可供參考
以上就是詳解Qt如何使用QtWebApp搭建Http服務(wù)器的詳細(xì)內(nèi)容,更多關(guān)于Qt QtWebApp搭建Http服務(wù)器的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C語言scandir函數(shù)獲取文件夾內(nèi)容的實(shí)現(xiàn)
scandir?函數(shù)用于列舉指定目錄下的文件列表,本文主要介紹了C語言scandir函數(shù)獲取文件夾內(nèi)容的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2024-03-03C++?Boost?weak_ptr智能指針超詳細(xì)講解
智能指針是一種像指針的C++對(duì)象,但它能夠在對(duì)象不使用的時(shí)候自己銷毀掉。雖然STL提供了auto_ptr,但是由于不能同容器一起使用(不支持拷貝和賦值操作),因此很少有人使用。它是Boost各組件中,應(yīng)用最為廣泛的一個(gè)2022-11-11C++實(shí)現(xiàn)LeetCode(228.總結(jié)區(qū)間)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(228.總結(jié)區(qū)間),本篇文章通過簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07C++11中l(wèi)onglong超長(zhǎng)整型和nullptr初始化空指針
本文介紹?C++11?標(biāo)準(zhǔn)中新添加的?long?long?超長(zhǎng)整型和?nullptr?初始化空指針,在?C++11?標(biāo)準(zhǔn)下,相比?NULL?和?0,使用?nullptr?初始化空指針可以令我們編寫的程序更加健壯,本文結(jié)合示例代碼給大家詳細(xì)講解,需要的朋友跟隨小編一起看看吧2022-12-12Microsoft?Visual?C++進(jìn)行調(diào)試的方法實(shí)現(xiàn)
VS功能極其強(qiáng)大,使用極其便利,本文主要介紹了Microsoft?Visual?C++進(jìn)行調(diào)試的方法實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2024-06-06C++報(bào)錯(cuò) XX does not name a type;
這篇文章主要給大家介紹了C++報(bào)錯(cuò) XX does not name a type;field `XX’ has incomplete type解決方案,文中通過代碼示例講解的非常詳細(xì),需要的朋友可以參考下2023-08-08