前面做了一些交互,网页是直接通过html对response进行返回的,这里QtWebApp与传统的web服务器不同,传统的web服务器可以调用同级目录相对路径或者绝对路径下的js,而QtWebApp的httpserver是response返回当前页面的问题,默认是无法调用的。 为了解决调用一些依赖的如echarts等一些js的代码模块引入的问题,就需要静态文件了。本篇解说StaticFileController,在返回的html文本中调用外部js文件,类似的,其他文件都是一样了,只是引入的后缀名不一样。
【资料图】
这里是调用静态文件js的
这里是重定向测试的
如果QtWebapp无法传递存储在服务器文件夹中的静态文件,那么它将是不完整的。StaticFileController提供了这一功能。但在使用它之前,需要在ini文件中进行一些额外的配置设置:
[files]path=../docrootencoding=UTF-8maxAge=90000cacheTime=60000cacheSize=1000000maxCachedFileSize=65536
需要一个指向StaticFileController实例的全局指针,以便整个程序都可以访问它。首先添加到global.h:
#ifndef GLOBAL_H#define GLOBAL_H#include "httpsessionstore.h"#include "staticfilefontroller.h"using namespace stefanfrings;extern HttpSessionStore* sessionStore;extern StaticFileController* staticFileController;#endif // GLOBAL_H
global.cpp:
#include "global.h"HttpSessionStore* sessionStore;StaticFileController* staticFileController;
在main.cpp中,配置StaticFileController的实例:
int main(int argc, char *argv[]){ QCoreApplication app(argc, argv); QString configFileName=searchConfigFile(); // Session store QSettings* sessionSettings=new QSettings(configFileName,QSettings::IniFormat,&app); sessionSettings->beginGroup("sessions"); sessionStore=new HttpSessionStore(sessionSettings,&app); // Static file controller QSettings* fileSettings=new QSettings(configFileName,QSettings::IniFormat,&app); fileSettings->beginGroup("files"); staticFileController=new StaticFileController(fileSettings,&app); // HTTP server QSettings* listenerSettings=new QSettings(configFileName,QSettings::IniFormat,&app); listenerSettings->beginGroup("listener"); new HttpListener(listenerSettings,new RequestMapper(&app),&app); return app.exec();}
现在可以在requestmapper.cpp中使用staticFileController:
#include "requestmapper.h"#include "httpsession.h"#include "global.h"void RequestMapper::service(HttpRequest& request, HttpResponse& response) { QByteArray path=request.getPath(); qDebug("RequestMapper: path=%s",path.data()); if (path=="/" || path=="/hello") { helloWorldController.service(request, response); } else if (path=="/list") { listDataController.service(request, response); } else if (path=="/login") { loginController.service(request, response); } else if (path=="/cookie") { cookieTestController.service(request, response); } else if (path.startsWith("/files")) { staticFileController->service(request,response); } else { response.setStatus(404,"Not found"); response.write("The URL is wrong, no such document."); } qDebug("RequestMapper: finished request");}
现在创建文件夹MyFirstWebApp/docroot/files,然后创建一个名为hello.HTML的HTML文件:
Hello World!
启动程序并打开http://localhost:8080/files/hello.html.浏览器将接收该文件的内容。 可以将其他文件(图像、css、javascript…)添加到该文件夹中,如果愿意,还可以创建更多的子文件夹。 如果出现“找不到文件”错误,调试消息将帮助找出服务器真正试图加载的文件。
有时想将浏览器重定向到另一个页面。这通常用于需要用户登录的网站。如果用户没有登录,他会被重定向到登录页面。当然,匿名用户必须可以访问登录页面本身。 requestmapper.cpp中的更改:
void RequestMapper::service(HttpRequest& request, HttpResponse& response) { QByteArray path=request.getPath(); qDebug("RequestMapper: path=%s",path.data()); QByteArray sessionId=sessionStore->getSessionId(request,response); if (sessionId.isEmpty() && path!="/login") { qDebug("RequestMapper: redirect to login page"); response.redirect("/login"); return; } else if (path=="/login") { ... } else if (path=="/whatever") { ... } qDebug("RequestMapper: finished request");}
HTTP服务器总是使用QByteArray而不是QString,原因很简单:性能。整个HTTP协议都是基于8位编码的,所以决定不浪费CPU时间,不必要地来回转换。但是当然可以使用Unicode。例子:
void UnicodeController::service(HttpRequest& request, HttpResponse& response) { QString chinese=QString::fromUtf8("美丽的花朵需要重症监护"); response.setHeader("Content-Type", "text/html; charset=UTF-8"); response.write(chinese.toUtf8(),true);}
这是谷歌翻译(不会说中文)提供的“美丽的花朵需要重症监护”的中文翻译。 从QString到UTF-8的转换并不比到Latin1的转换慢。因此,如果需要,请随时使用Unicode。但千万不要忘记使用QString::fromUtf8。如果只写中文=“美丽的花朵需要重症监护“,只会得到乱码。
准备之前的demo v1.4.0模板:
maxCachedFileSize=65536
新增静态配置,路径调整问exe当前的子目录www(符合后端基本习惯)
[files]path=../wwwencoding=UTF-8maxAge=90000cacheTime=60000cacheSize=1000000
必须分流,静态文件指示的api和文件是先从处理过程然后再到静态文件管理类的,所以有些是请求数据则需要在代码中处理,这里之前是没有这样做,可查看“入坑一”。
本Demo无法打开跳转的staticFileUserJs,可查看“入坑二” 本Demo静态文件无法调用js,请查看“入坑三”。
[listener];ip=127.0.0.1port=8080readTimeout=60000maxRequestSize=16000maxMultiPartSize=10000000minThreads=4maxThreads=100cleanupInterval=60000[logging]fileName=../logs/httpserver.log;fileName=/dev/stdoutminLevel=CRITICALbufferSize=100maxSize=1000000maxBackups=2;timestampFormat=dd.MM.yyyy hh:mm:ss.zzztimestampFormat=yyyy-MM-dd hh:mm:ss.zzzmsgFormat={timestamp} {typeNr} {type} {thread} {msg};QT5 supports: msgFormat={timestamp} {typeNr} {type} {thread} {msg}\n in {file} line {line} function {function}[files]path=../wwwencoding=UTF-8maxAge=90000cacheTime=60000cacheSize=1000000maxCachedFileSize=65536
长沙红胖子Qt 你好, 长沙红胖子 QQ:21497936 www.hpzwl.com
长沙红胖子Qt <script>function reset() {document.getElementById("dt1").innerHTML="---.---";document.getElementById("dt2").innerHTML="---.---";document.getElementById("dt3").innerHTML="---.---";}function getDt1() {var xhr = new XMLHttpRequest();xhr.open("GET","/checkState/data",true);xhr.send();xhr.onreadystatechange = function() {if(xhr.readyState === 4 && xhr.status === 200){document.getElementById("dt1").innerHTML = xhr.responseText;}}}</script><script src="jquery.min.js"></script><script>function doJs() {alert($("li")[0]);}</script>
#ifndef STATICFILEMANAGER_H#define STATICFILEMANAGER_H#include #include #include "httplistener.h"#include "staticfilecontroller.h"using namespace stefanfrings;class StaticFileManager : public QObject{ Q_OBJECTprivate: explicit StaticFileManager(QObject *parent = 0);public: static StaticFileManager *getInstance();public: StaticFileController *getStaticFileController() const;public: void setStaticFileController(StaticFileController *pStaticFileController);private: static StaticFileManager *_pInstance; static QMutex _mutex;private: StaticFileController *_pStaticFileController;};#endif // STATICFILEMANAGER_H
#include "StaticFileManager.h"#include "IndexRequestHandler.h"#include "HttpSessionStoreManager.h"#include #include #include #include //#define LOG qDebug()<<__FILE__<<__LINE__//#define LOG qDebug()<<__FILE__<<__LINE__<<__FUNCTION__//#define LOG qDebug()<<__FILE__<<__LINE__<
#ifndef INDEXREQUESTHANDLER_H#define INDEXREQUESTHANDLER_H#include "httprequesthandler.h"#include "HelloWorldRequestHandler.h"#include "ListRequestHandler.h"#include "LoginRequestHandler.h"#include "CheckStateRequestHandler.h"using namespace stefanfrings;class IndexRequestHandler : public HttpRequestHandler{public: IndexRequestHandler(QObject *parent = 0);public: void service(HttpRequest& request, HttpResponse& response);private: QTextCodec *_pTextCodec;private: HelloWorldRequestHandler _helloWorldRequestHandler; // hellowold消息处理 ListRequestHandler _listRequestHandler; // list消息处理 LoginRequestHandler _loginRequestHandler; // login消息处理,Demo v1.3.0 CheckStateRequestHandler _checkStateRequestHandler; // checkState实时检测状态};#endif // INDEXREQUESTHANDLER_H
#include "IndexRequestHandler.h"#include "StaticFileManager.h"#include #include #include //#define LOG qDebug()<<__FILE__<<__LINE__//#define LOG qDebug()<<__FILE__<<__LINE__<<__FUNCTION__//#define LOG qDebug()<<__FILE__<<__LINE__<" "" "" "" "" "" "长沙红胖子Qt " "" "" " 你好, 长沙红胖子 QQ:21497936 www.hpzwl.com
" " " " " " " " " " " ""; QByteArray byteArray = str.toUtf8(); response.write(byteArray);#else // index使用文件 LOG << path; StaticFileManager::getInstance()->getStaticFileController()->service(request, response);#endif }else if(path == "/helloworld") { _helloWorldRequestHandler.service(request, response); }else if(path == "/list") { _listRequestHandler.service(request, response); }else if(path == "/login" || path == "/login/out") { _loginRequestHandler.service(request, response); }else if(path == "/checkState" || path == "/checkState/data") { _checkStateRequestHandler.service(request, response); }else if( path.startsWith("/staticFileUseJs") || path == "/favicon.ico" || path.endsWith(".js")) { LOG << path; StaticFileManager::getInstance()->getStaticFileController()->service(request, response); }else {#if 0 LOG; response.setStatus(404,"Not found"); QString str; str = "The URL is wrong, no such document."; QByteArray byteArray = str.toUtf8(); response.write(byteArray);#else // 这里进行重定向 LOG << "重定向至/"; response.redirect("/");#endif }}
Ajax未代码捕捉,直接入静态文件本身就无法变成api接口了。
加载的静态文件,里面请求的任何东西只要调用静态文件处理类来处理,则会都变成本地静态文件(这里静态文件主要是可以调用未传递过去到客户端的文件,如.js文件等)
先得从一个头部文件开始分流,一开始使用一个自定义的代码消息处理,这个消息处理通过第一层路径或者子路径来判断是否是静态文件,后再扔给静态文件,就可以绕开。 而接口也是通过路径进行判断,然后用代码进行返回,所以这种开发起来就混合了Qt和httpJs等静态文件了。
去掉js的代码,未恢复正常 去掉js的文件,未恢复正常 检查代码发现,是重定向问题 请查询发现,favicon,即Favorites Icon的缩写,顾名思义,便是其可以让浏览器的收藏夹中除显示相应的标题外,还以图标的方式区别不同的网站,就是网站的图标。 没有图标本来为空,而我们没有分流该路径,分流之后还是不行,再测试:
经过摸索,还发现: 再后来发现,静态文件这个是文件,需要后缀html,因为我们做qt的这块使用代码api习惯了,导致忽略了这点
但是点击没有弹窗:
检查,未放开.js,加载js没有真的加载进去 在静态文件分流的地方,放开后缀.js的
还是不行,测试发现必须引入js在单独空的script里面。
且发现要分开:
潮新闻客户端6月15日,国家体育总局科教司公示了2023年优秀运动员本科
6月15日,回天新材(300041)融资买入673 78万元,融资偿还952 44万元
猪肉股震荡走高,巨星农牧(603477)大涨7%,新五丰(600975)、金新农(002
负责人:根据2023年普通高等学校招生工作规定,军队院校须对省级招委会
无边界这是美团给外界的印象如今的美团已不再仅仅是团购外卖版图已经拓
X 关闭
X 关闭