详解Qt如何使用QtWebApp搭建Http服务器

 更新时间:2024年12月30日 10:47:19   作者:小灰灰搞电子  
这篇文章主要为大家详细介绍了Qt如何使用QtWebApp搭建Http服务器,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下

一、QtWebApp源码下载

a 、下载地址

http://www.stefanfrings.de/qtwebapp/QtWebApp.zip

b、 源码目录

二、http服务器搭建

a、使用qt creater新建一个项目

b、将QtWebApp的源码拷贝到工程中

c、新建一个httpServer的类,继承stefanfrings::HttpRequestHandler

需要包含相关头文件

#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为配置文件内容如下:

[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 为文件的根目录

三、启动http服务器

在mainwindow中新建一个HttpServer 变量,然后实例化,

此时http服务器已经启动了。

四、获取http服务器文件

a、打开浏览器输入http://localhost:8080/filename就能下载到文件名为filename的文件了。

b、我的程序中只实现了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服务器的详细内容,更多关于Qt QtWebApp搭建Http服务器的资料请关注脚本之家其它相关文章!

相关文章

  • C++实现LeetCode(209.最短子数组之和)

    C++实现LeetCode(209.最短子数组之和)

    这篇文章主要介绍了C++实现LeetCode(209.最短子数组之和),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-08-08
  • C++实现String与UF8互转

    C++实现String与UF8互转

    这篇文章介绍了C++实现String与UF8互转的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-05-05
  • C语言结构体,枚举,联合体详解

    C语言结构体,枚举,联合体详解

    下面小编就为大家带来一篇全面了解C语言结构体,枚举,联合体。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2021-09-09
  • C 语言中strstr函数实例详解

    C 语言中strstr函数实例详解

    这篇文章主要介绍了C 语言中strstr函数实例详解的相关资料,需要的朋友可以参考下
    2017-07-07
  • C++实现扫雷小游戏(控制台版)

    C++实现扫雷小游戏(控制台版)

    这篇文章主要为大家详细介绍了C++实现控制台版的扫雷小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-03-03
  • C++中的封装、继承、多态理解

    C++中的封装、继承、多态理解

    这篇文章主要介绍了C++中的封装、继承、多态介绍,需要的朋友可以参考下
    2020-01-01
  • 简述C++11就地初始化与列表初始化

    简述C++11就地初始化与列表初始化

    这篇文章主要介绍了C++11就地初始化与列表初始化的相关资料,帮助大家更好的理解和学习C++,感兴趣的朋友可以了解下
    2020-08-08
  • 解析C语言与C++的编译模型

    解析C语言与C++的编译模型

    C++继承了C的编译模型,C语言的编译链接模型相对简洁,但C++继承了这些机制之后变得更加复杂难以理解,这里就来带大家简要解析C语言与C++的编译模型
    2016-05-05
  • 利用Matlab实现绘制中秋山间秋月和皓月当空效果

    利用Matlab实现绘制中秋山间秋月和皓月当空效果

    中秋节还有三天就到了,中秋节啊,阖家团圆的日子。本文将利用Matlab绘制中秋山间秋月和皓月当空的动态效果,感兴趣的可以了解一下
    2022-09-09
  • C语言结构体的全方面解读

    C语言结构体的全方面解读

    C 数组允许定义可存储相同类型数据项的变量,结构是 C 编程中另一种用户自定义的可用的数据类型,它允许你存储不同类型的数据项
    2021-10-10

最新评论