詳解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的類(lèi),繼承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、打開(kāi)瀏覽器輸入http://localhost:8080/filename就能下載到文件名為filename的文件了。
b、我的程序中只實(shí)現(xiàn)了zip文件,如果是其他類(lèi)型文件需要修改一下地方

為

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)文章
Qt實(shí)現(xiàn)將qsqlite數(shù)據(jù)庫(kù)中的數(shù)據(jù)導(dǎo)出為Excel表格
這篇文章主要為大家詳細(xì)介紹了如何通過(guò)Qt實(shí)現(xiàn)將qsqlite數(shù)據(jù)庫(kù)中的數(shù)據(jù)導(dǎo)出為Excel表格,文中的示例代碼簡(jiǎn)潔易懂,有需要的小伙伴可以了解一下2024-12-12
C++中關(guān)于=default和=delete問(wèn)題
這篇文章主要介紹了C++中關(guān)于=default和=delete問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07
C語(yǔ)言線(xiàn)性表順序表示及實(shí)現(xiàn)
這篇文章主要介紹了C語(yǔ)言線(xiàn)性表順序表示及實(shí)現(xiàn),線(xiàn)性表是最常用且最簡(jiǎn)單的一種數(shù)據(jù)結(jié)構(gòu)。簡(jiǎn)而言之,一個(gè)線(xiàn)性表是n個(gè)數(shù)據(jù)元素的有限序列2022-07-07
C語(yǔ)言使用DP動(dòng)態(tài)規(guī)劃思想解最大K乘積與乘積最大問(wèn)題
Dynamic Programming動(dòng)態(tài)規(guī)劃方法采用最優(yōu)原則來(lái)建立用于計(jì)算最優(yōu)解的遞歸式,并且考察每個(gè)最優(yōu)決策序列中是否包含一個(gè)最優(yōu)子序列,這里我們就來(lái)展示C語(yǔ)言使用DP動(dòng)態(tài)規(guī)劃思想解最大K乘積與乘積最大問(wèn)題2016-06-06
Java3D實(shí)例之創(chuàng)建空間幾何模型的實(shí)現(xiàn)方法
本篇文章是對(duì)Java3D 創(chuàng)建空間幾何模型的實(shí)現(xiàn)方法進(jìn)行了詳細(xì)的介紹。需要的朋友參考下2013-05-05
c++ signal實(shí)現(xiàn)發(fā)送信號(hào)
這篇文章主要為大家詳細(xì)介紹了c++ signal實(shí)現(xiàn)發(fā)送信號(hào)的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-01-01
C語(yǔ)言的動(dòng)態(tài)內(nèi)存分配及動(dòng)態(tài)內(nèi)存分配函數(shù)詳解
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言的動(dòng)態(tài)內(nèi)存分配及動(dòng)態(tài)內(nèi)存分配函數(shù),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助2022-03-03
C++聲明extern變量和extern函數(shù)的用法
extern關(guān)鍵字可以用來(lái)聲明變量和函數(shù)作為外部變量或者外部函數(shù)供其它文件使用,所以本文給大家介紹了C++聲明extern變量和extern函數(shù)的用法,文中有相關(guān)的代碼示例供大家參考,需要的朋友可以參考下2024-11-11
Visual?Studio?2022下載安裝與使用超詳細(xì)教程
這篇文章主要介紹了Visual?Studio?2022最新版安裝與使用教程,本文以社區(qū)版為例通過(guò)圖文并茂的形式給大家介紹Visual?Studio?2022安裝使用,需要的朋友可以參考下2022-04-04

