Search code examples
pythonflashpyqt5qtwebengine

How to load swf file to QWebEngineView from memory


i am trying to load flash (swf) file using QWebEngineView i want to load the swf from memory but i was only able to load it from a URL so far

data is a bytearray of the result of urlopen (urllib). self.webview is an instance of QWebEngineView.

self.webview.load(QtCore.QUrl(url))              # works
self.webview.setContent(QtCore.QByteArray(data)) # does not work

using a URL the swf runs. loading from the bytearray results in empty page or page with gibberish. no errors are showing.

i am using pyqt5 with python3


Solution

  • It seems that you cannot pass the raw-data directly so a workaround is to create a custom QWebEngineUrlSchemeHandler that provides the resource through a url:

    from PyQt5 import QtCore, QtWidgets, QtWebEngineCore, QtWebEngineWidgets
    
    
    class CustomUrlSchemeHandler(QtWebEngineCore.QWebEngineUrlSchemeHandler):
        SCHEMENAME = b"custom"
    
        def __init__(self, parent=None):
            super().__init__(parent)
            self._datas = dict()
    
        def add_data(self, path, mimetype, data):
            self._datas[path] = mimetype, data
            url = QtCore.QUrl()
            url.setScheme(self.SCHEMENAME.decode())
            url.setPath(path)
            return url
    
        def requestStarted(self, job):
            requestMethod = job.requestMethod()
            if requestMethod != b"GET":
                job.fail(QtWebEngineCore.QWebEngineUrlRequestJob.RequestDenied)
                return
    
            requestUrl = job.requestUrl()
            requestPath = requestUrl.path()
            value = self._datas.get(requestPath)
            if value is not None:
                mimetype, data = value
                buf = QtCore.QBuffer(parent=self)
                job.destroyed.connect(buf.deleteLater)
                buf.open(QtCore.QIODevice.WriteOnly)
                buf.write(data)
                buf.close()
                job.reply(mimetype.encode(), buf)
            else:
                job.fail(QtWebEngineCore.QWebEngineUrlRequestJobUrlNotFound)
    
        @classmethod
        def registerUrlScheme(cls):
            scheme = QtWebEngineCore.QWebEngineUrlScheme(cls.SCHEMENAME)
            QtWebEngineCore.QWebEngineUrlScheme.registerScheme(scheme)
    
    
    if __name__ == "__main__":
    
        import sys
        import urllib.request
    
        data = b""
        with urllib.request.urlopen(
            "https://condor.depaul.edu/sjost/hci430/flash-examples/swf/wheel.swf"
        ) as response:
            data = response.read()
    
        CustomUrlSchemeHandler.registerUrlScheme()
    
        app = QtWidgets.QApplication(sys.argv)
    
        settings = QtWebEngineWidgets.QWebEngineSettings.defaultSettings()
        settings.setAttribute(QtWebEngineWidgets.QWebEngineSettings.PluginsEnabled, True)
    
        view = QtWebEngineWidgets.QWebEngineView()
    
        handler = CustomUrlSchemeHandler()
        view.page().profile().installUrlSchemeHandler(handler.SCHEMENAME, handler)
    
        view.resize(640, 480)
        view.show()
    
        url = handler.add_data("test.swg", "application/x-shockwave-flash", data)
        view.load(url)
    
        sys.exit(app.exec_())