Qt(QtWebEngine)加载本地网页跨域问题的总结

简介: Qt(QtWebEngine)加载本地网页跨域问题的总结

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. 参考

  1. Qt QWebEngineView not allowed to load local resource
  2. PyQt5 How To Use JavaScript Modules

分类: QT

标签: QT , 网页 , 跨域


相关文章
|
5月前
|
XML Linux 数据格式
Qt对Word网页的读写功能实现
Qt对Word网页的读写功能实现
318 9
|
Web App开发 编译器 C语言
QT5.14.2使用webkit引擎完成网页浏览
QT5.14.2使用webkit引擎完成网页浏览
1500 0
QT5.14.2使用webkit引擎完成网页浏览
|
安全 JavaScript 编译器
QT调用IE浏览器COM插件完成网页浏览
QT调用IE浏览器COM插件完成网页浏览
746 0
QT调用IE浏览器COM插件完成网页浏览
|
安全 IDE 小程序
QT应用编程: Visual Studio里编写activex控件在网页中运行(dll插件形式)
QT应用编程: Visual Studio里编写activex控件在网页中运行(dll插件形式)
400 0
QT应用编程: Visual Studio里编写activex控件在网页中运行(dll插件形式)
|
数据安全/隐私保护 C++ 计算机视觉
Qt(C++)开发一款图片防盗用水印制作小工具
文本水印是一种常用的防盗用手段,可以将文本信息嵌入到图片、视频等文件中,用于识别和证明文件的版权归属。在数字化和网络化的时代,大量的原创作品容易被不法分子盗用或侵犯版权,因此加入文本水印成为了保护原创作品和维护知识产权的必要手段。 通常情况下,文本水印可以包含版权声明、制作者姓名、日期、网址等信息,以帮助识别文件的来源和版权归属。同时,为了增强防盗用效果,文本水印通常会采用字体、颜色、角度等多种组合方式,使得水印难以被删除或篡改,有效地降低了盗用意愿和风险。 开发人员可以使用图像处理技术和编程语言实现文本水印的功能,例如使用Qt的QPainter类进行文本绘制操作,将文本信息嵌入到图片中,
588 1
Qt(C++)开发一款图片防盗用水印制作小工具
|
监控 C++ 容器
【qt】MDI多文档界面开发
【qt】MDI多文档界面开发
767 0
|
C++
C++ Qt开发:QUdpSocket网络通信组件
QUdpSocket是Qt网络编程中一个非常有用的组件,它提供了在UDP协议下进行数据发送和接收的能力。通过简单的方法和信号,可以轻松实现基于UDP的网络通信。不过,需要注意的是,UDP协议本身不保证数据的可靠传输,因此在使用QUdpSocket时,可能需要在应用层实现一些机制来保证数据的完整性和顺序,或者选择在适用的场景下使用UDP协议。
1062 2
|
存储 运维 监控
Qt开发网络嗅探器01
Qt开发网络嗅探器01

推荐镜像

更多
  • qt