如何在PyQt5的QWebEngineView中显示字节流格式PDF?
解决PyQt5 QWebEngineView加载PDF字节流的问题
你尝试用QtCore.QUrl.fromEncoded()加载PDF字节流失败,是因为这个方法的作用是解析编码后的URL字符串,而非直接加载文件内容字节流。要实现从字节流加载PDF到QWebEngineView,有两种可行方案:
方案一:使用Data URI(最简单直接)
将PDF字节流编码为Base64格式,构造符合Data URI规范的字符串,直接让QWebEngineView加载这个URI即可。
修改后的完整代码
from PyQt5 import QtWidgets from PyQt5 import QtCore from PyQt5 import QtWebEngineWidgets import sys import base64 application = QtWidgets.QApplication(sys.argv) window = QtWidgets.QWidget() window_layout = QtWidgets.QGridLayout() # 模拟从数据库读取的PDF字节流(这里用本地文件演示) PDF_PATH = "D:\\export.pdf" with open(PDF_PATH, "rb") as f: PDF_as_bytes = f.read() # 将字节流转为Base64编码的字符串 pdf_base64 = base64.b64encode(PDF_as_bytes).decode("utf-8") # 构造Data URI data_uri = f"data:application/pdf;base64,{pdf_base64}" engine = QtWebEngineWidgets.QWebEngineView() engine.setMinimumSize(500, 500) engine_settings = engine.settings() engine_settings.setAttribute(QtWebEngineWidgets.QWebEngineSettings.PluginsEnabled, True) engine_settings.setAttribute(QtWebEngineWidgets.QWebEngineSettings.ShowScrollBars, True) engine_settings.setAttribute(QtWebEngineWidgets.QWebEngineSettings.PdfViewerEnabled, True) # 加载Data URI engine.load(QtCore.QUrl.fromUserInput(data_uri)) window_layout.addWidget(engine) window.setLayout(window_layout) window.show() application.exec()
关键说明
base64.b64encode()把PDF字节流转成Base64编码的字节串,再用decode("utf-8")转为字符串- Data URI格式为
data:application/pdf;base64,<Base64编码内容>,QWebEngineView原生支持这种格式加载PDF
方案二:自定义URL Scheme Handler(适合复杂场景)
如果需要频繁从字节流加载PDF,或者要处理动态生成的PDF内容,可以自定义一个URL Scheme Handler,注册专属Scheme(比如pdfstream://),当加载该Scheme的URL时,返回对应的字节流数据。
代码示例
from PyQt5 import QtWidgets from PyQt5 import QtCore from PyQt5 import QtWebEngineWidgets import sys class PdfStreamHandler(QtWebEngineWidgets.QWebEngineUrlSchemeHandler): def __init__(self, pdf_bytes, parent=None): super().__init__(parent) self._pdf_bytes = pdf_bytes def requestStarted(self, request): # 创建响应 response = QtWebEngineWidgets.QWebEngineUrlRequestJob.Response() response.setHeader(b"Content-Type", b"application/pdf") response.setHeader(b"Content-Length", str(len(self._pdf_bytes)).encode()) # 写入字节流数据 request.reply(b"application/pdf", self._pdf_bytes) application = QtWidgets.QApplication(sys.argv) # 注册自定义Scheme scheme = QtCore.QUrlScheme(b"pdfstream") scheme.setFlags(QtCore.QUrlScheme.SecureScheme | QtCore.QUrlScheme.LocalScheme) QtCore.QUrlScheme.registerScheme(scheme) window = QtWidgets.QWidget() window_layout = QtWidgets.QGridLayout() # 模拟从数据库读取的PDF字节流 PDF_PATH = "D:\\export.pdf" with open(PDF_PATH, "rb") as f: PDF_as_bytes = f.read() engine = QtWebEngineWidgets.QWebEngineView() engine.setMinimumSize(500, 500) engine_settings = engine.settings() engine_settings.setAttribute(QtWebEngineWidgets.QWebEngineSettings.PluginsEnabled, True) engine_settings.setAttribute(QtWebEngineWidgets.QWebEngineSettings.ShowScrollBars, True) engine_settings.setAttribute(QtWebEngineWidgets.QWebEngineSettings.PdfViewerEnabled, True) # 添加自定义Handler handler = PdfStreamHandler(PDF_as_bytes) engine.page().profile().installUrlSchemeHandler(b"pdfstream", handler) # 加载自定义Scheme的URL engine.load(QtCore.QUrl("pdfstream://local/pdf")) window_layout.addWidget(engine) window.setLayout(window_layout) window.show() application.exec()
关键说明
- 自定义
PdfStreamHandler继承自QWebEngineUrlSchemeHandler,重写requestStarted方法处理请求并返回PDF字节流 - 注册自定义Scheme时要设置合适的Flags,确保QWebEngineView信任该Scheme
- 加载时使用自定义Scheme的URL(比如
pdfstream://local/pdf),Handler会自动返回对应的字节流
内容的提问来源于stack exchange,提问作者Mohammed almalki
相关产品推荐
相关产品推荐

