Qt(QtWebEngine)加载本地网页跨域问题的总结
1. 概述
浏览器直接加载本地网页的时候,如果网页涉及到加载本地资源(如图片),会出现跨域的问题。Qt的Qt WebEngine模块基于Chromium项目,遇到这样的情况也会出现跨域的问题。
2. 详论
2.1. 传参
理论上,我们可以像设置chrome浏览器跨域一样(设置chrome浏览器跨域网上的资料非常多),给我们使用的Qt程序传参:
char ARG_DISABLE_WEB_SECURITY[] = "--disable-web-security";
int newArgc = argc+1+1;
char** newArgv = new char*[newArgc];
for(int i=0; i<argc; i++) {
newArgv[i] = argv[i];
}
newArgv[argc] = ARG_DISABLE_WEB_SECURITY;
newArgv[argc+1] = nullptr;
QApplication myApplication(newArgc, newArgv);
Qt会将跨域参数传递到Qt WebEngine模块的Chromium内核中,从而实现跨域。
2.2. JS module
即使设置跨域,当使用JavaScript ES6 module的时候,仍然有可能会出现跨域的问题。
一个显而易见的错误提示如下:
js: Failed to load module script: The server responded with a non-JavaScript MIME type of "". Strict MIME type checking is enforced for module scripts per HTML spec.
原因在于,在Chrome浏览器的某些版本中,ES6 module的功能不支持跨域(但是require.js却可以)。现在最新版本的Chrome的跨域设置已经可以支持ES6 module,但是Qt WebEngine模块却可能是比较低的Chromium版本,从而造成使用ES6 module遇到跨域问题。通常来说,越新的Qt版本,Chromium版本也会越高。
如果还是不想要服务器环境,那么一种解决方案就是自定义URL方案:
#include <QApplication>
#include <QWebEngineView>
#include <QWebEngineUrlScheme>
#include <QWebEngineProfile>
#include <QWebEngineUrlSchemeHandler>
#include <QWebEngineUrlRequestJob>
#include <QFile>
#include <QFile>
#include <QFileInfo>
#include <QMimeDatabase>
class QtSchemeHandler : public QWebEngineUrlSchemeHandler
{
public:
QtSchemeHandler(QObject *parent = nullptr):QWebEngineUrlSchemeHandler(parent)
{
}
void requestStarted(QWebEngineUrlRequestJob *request) override
{
QByteArray request_method = request->requestMethod();
if(request_method != "GET")
{
request->fail(QWebEngineUrlRequestJob::RequestDenied);
return;
}
QUrl request_url = request->requestUrl();
QString request_path = request_url.path();
//qDebug()<<request_url<<endl;
QString application_path = "D:/";
QFile *file = new QFile(application_path + request_path);
file->setParent(request);
connect(request, &QObject::destroyed, file, &QFile::deleteLater);
//qDebug()<<file->size()<<endl;
if(!file->exists()||file->size()==0)
{
printf("resource '{request_path}' not found or is empty");
request->fail(QWebEngineUrlRequestJob::UrlNotFound);
return;
}
QFileInfo file_info = QFileInfo(*file);
QMimeDatabase mime_database;
QMimeType mime_type = mime_database.mimeTypeForFile(file_info);
request->reply(QUrl(mime_type.name()).toEncoded(), file);
}
};
int main(int argc, char *argv[])
{
char ARG_DISABLE_WEB_SECURITY[] = "--disable-web-security";
int newArgc = argc+1+1;
char** newArgv = new char*[newArgc];
for(int i=0; i<argc; i++) {
newArgv[i] = argv[i];
}
newArgv[argc] = ARG_DISABLE_WEB_SECURITY;
newArgv[argc+1] = nullptr;
qputenv("QTWEBENGINE_REMOTE_DEBUGGING", "7542"); //用于调试
QWebEngineUrlScheme scheme = QWebEngineUrlScheme("qt");
scheme.setFlags(QWebEngineUrlScheme::CorsEnabled);
QWebEngineUrlScheme::registerScheme(scheme);
//QApplication a(argc, argv);
QApplication a(newArgc, newArgv);
QWebEngineView view;
QtSchemeHandler *scheme_handler = new QtSchemeHandler();
view.page()->profile()->installUrlSchemeHandler("qt", scheme_handler);
view.page()->profile()->clearHttpCache(); //删除缓存
//view.load(QUrl("D:/cesium/CesiumWork/3DTilesPhotogrammetry/3DTilesPhotogrammetry.html"));
view.load(QUrl("qt://local/cesium/CesiumWork/3DTilesPhotogrammetry/3DTilesPhotogrammetry.html"));
view.show();
return a.exec();
}
这个方案的本质是将URL定义地址的资源给转发了一遍。但是这种方案还是有局限性,经过测试,在Qt5.15.2版本中可行,但在Qt5.12.5版本中不行。而且这样所有的资源地址都得采用这一套URL方案。
3. 建议
其实个人还是不太建议再轻易尝试使用本地网页跨域了,毕竟这一点与Web的安全性背道而驰。最好还是让网页在服务器环境下吧,出问题的可能性会小一点。
4. 参考
Qt(QtWebEngine)加载本地网页跨域问题的总结的更多相关文章
- Android 中加载本地Html 跨域问题,http协议允许加载
一.需求: 后台加载HTML的包时间太长,太卡,让把所有的HTML包放到前台:使用的是file://协议,有些内容和样式加载不出来,H5那边说需要用http://协议来加载: 二.处理过程: 安卓最简 ...
- 阿里云对象存储OSS————跨域资源共享(CORS)(m3u8 无法加载m3u8:跨域访问被拒绝)
今天在做视频直播录像的时候,添加一个录制APP的.M3U8文件到OSS的一个test文件中存储,结果是访问不到了: 提示:无法加载m3u8:跨域访问被拒绝!!!!! 项目代码测试地址:https:// ...
- Qt5 webview加载本地网页
文件结构 qtchart.pro QT += core gui webkitwidgets greaterThan(QT_MAJOR_VERSION, 4): QT += widgets TARGET ...
- qt webengineview 加载本地资源方式
一.如果把资源添加到本地资源qrc库里了,请使用 ui->preview->setUrl(QUrl("qrc:/HelloWorld2.html")): 二.如果没有现 ...
- Jquery的load加载本地文件出现跨域错误的解决方案
如果用原生的AJAX是加载本地文件就不会出现错误.当然,这个jquery的load放在服务器上通过http加载还是支持的.也有例外比如在firefox和ie浏览器使用$.ajax加载本地html或tx ...
- Swift - 网页控件(UIWebView)加载本地数据,文件
使用UIWebView加载本地数据或资源有如下三种方式: 1,使用loadHTMLString方法加载HTML内容 2,使用loadRequest方法加载本地资源(也可用于加载服务器资源) 3,先将内 ...
- wpf中使用cefsharp加载本地html网页并实现cs和js的交互,并且cefsharp支持any cpu
废话少说,直接上代码: 第一步: 第二步: 第三步: 第四步: App.xaml.cs对应的代码: using CefSharp; using CefSharp.Wpf; using System; ...
- WKWebView 加载本地HTML显示不出网页问题,这点你注意了吗?-------完美显示
1.首先,WKWebView的引入和创建,我这里就不做阐述,我要说的,就是解决别人不能给您解决的问题 2.WKWebView 加载本地HTML,也就是两三句代码 是吧?作为读者的您肯定也知道,也实现 ...
- WebView加载本地html、js文件常见问题及解决办法
声明:基于android studio平台,php语言搭建服务器 目录: 一.JavaScript脚本语言没有反应 二.alert无法弹出 三.html页面之间不能跳转 四.屏幕缩放没有达到预期效果 ...
随机推荐
- idea在新窗口中打开
IntelliJ IDEA 2018.1.4 x64版本同时打开多个窗口可以进行如下设置,找到file--Settings...,然后会弹出下面的窗口:然后注意红框里的勾选项,最后确定Apply,OK ...
- 微服务部署 docker-compose
1.docker-maven-plugin 介绍 在我们持续集成过程中,项目工程一般使用 Maven 编译打包,然后生成镜像,通过镜像上线,能够大大提供上线效率,同时能够快速动态扩容,快速回滚,着实很 ...
- 使用postman进行post请求传递中文导致后台接收乱码的问题
1.个人猜测估计是如果header里不指明编码的话,经过tomcat服务器时会导致转换乱码信息,这样就算你在filter里配置了EncodingFilter相关的过滤器也无济于事.. 解决方法就是在h ...
- 编译器如何处理C++不同类中同名函数(参数类型个数都相同)
转载请注明出处,版权归作者所有 lyzaily@126.com yanzhong.lee 作者按: 从这篇文章中,我们主要会认识到一下几点: 一.不类中的特征标相同的同名函数,它们是不同的函数,原因就 ...
- 一步步搭建物联网系统——无处不在的CSS
无处不在的CSS 或许你觉得CSS一点儿也不重要,而事实上,如果说HTML是建筑的框架,CSS就是房子的装修.那么Javascript呢,我听到的最有趣的说法是小三--还是先让我们回到代码上来吧. C ...
- [护网杯 2018]easy_tornado 1
复现一道关于tornado的题目 首先可以得知此题用的是tornado,基于python的后端框架,多半是ssti注入 有三个文件,首先可得知flag在何处 然后观察hint和url就知道要根据coo ...
- 何使用派生类指针指向基类,即downcast向下转型?
基类指针指向派生类,我们已经很熟了.假如我们想用派生类反过来指向基类,就需要有两个要求:1)马克-to-win:基类指针开始时指向派生类,2)我们还需要清清楚楚的转型一下. if you want t ...
- Java实现链表反转(借助栈实现)
public class ListNode { int val; ListNode next = null; ListNode(int val) { this.val = val; } // 添加新的 ...
- Python:爬取中国各市的疫情数据并存储到数据库
import requests import pymysql import json def create(): # 连接数据库 db = pymysql.connect(host = 'localh ...
- getHibernateTemplate出现的所有find方法的总结
文章转自:http://www.cnblogs.com/DarrenChan/p/5528194.html 一.find(String queryString); 示例:this.getHiberna ...