使用 electron 打包成 exe 安装文件后,PDF.js 自定义 viewer.html 预览 pdf 时,可能会出现预览路径加载不对的问题,还有右键复制功能无效的问题,都需要特殊处理
1. pdfjs 预览加载路径不对
直接使用浏览器内置的 pdf 阅读器预览,无论是在线网站运行,还是 electron 打包后,预览均没有问题,缺点是页面无法自定义,不够灵活。
使用 pdfjs 自定义页面 viewer.html 预览,网站运行时,没有问题
但是 electron 打包后,pdf 加载路径就不对了,有跨域问题,electron开发好难搞呀
1.1 网站在线运行
jsx
<iframe
title="预览文档"
src="/web/mViewer.html?file=../pdf/15.pdf"
width="100%"
height="100%"
></iframe>
在线运行时,本地启动服务地址为http://localhost:3000
pdf 文档预览调用链,如下所示:
http://localhost:3000/web/mViewer.html?file=../pdf/15.pdf
-> http://localhost:3000/pdf/15.pdf
控制台显示如下:
1.2 electron 打包后运行
使用 electron 打包后,pdfjs 加载离线的 pdf 文件就会报错
报错信息如下所示:
Request URL: file:///web/mViewer.html?file=../pdf/15.pdf
Referrer Policy: no-referrer
解决方案:在 iframe 标签的 src 属性中使用相对路径或者绝对路径
链接到 pdfjs 的相关资源。
我使用了process.env.PUBLIC_URL
,增加了referrerPolicy="no-referrer"
配置,确保在打包编译后生成的文件中,相关资源能够正确加载。
配置了之后,在线运行也是没问题的。
jsx
<iframe
ref={iframeRef}
title="预览文档"
src={`${process.env.PUBLIC_URL}/web/mViewer.html?file=${
"." + curSubmenu.pdfPath
}#page=${curSubmenu.pdfStartPage}`}
width="100%"
height="100%"
referrerPolicy="no-referrer"
></iframe>
更改配置后,electron 中 pdf 文档预览时,加载路径如下所示:
2. pdfjs 右键复制功能
网站运行时,pdf 文档预览,可以选中文本,然后右键复制
也可以选中后,用 ctrl+c 快捷键复制,这是浏览器自带的功能。
但是使用 electron 打包后,选中pdf文本后,默认右键是没有功能的
需要自己处理右键菜单,要在main.js
中添加复制功能,如下所示:
js
const { Menu, MenuItem } = require("electron");
// 创建上下文菜单
const contextMenu = new Menu();
contextMenu.append(
new MenuItem({
label: "复制",
role: "copy",
})
);
// 在 PDF 预览窗口上绑定上下文菜单
win.webContents.on("context-menu", (e, params) => {
contextMenu.popup(win, params.x, params.y);
});
展示效果如下图所示:
3. 复制当前 pdf 页文本
项目要求,需要自定义按钮
实现复制当前 pdf 页文本内容,目前插件是不支持的。
我的实现方案是,获取到页码和页面元素,使用textContent
属性获取文本内容
直接查看源码,获取对应元素,如下所示:
data-page-number=11
中的11可以替换成变量
js
// 定义iframe元素
const iframeRef = useRef < HTMLIFrameElement > null;
// 复制方法
function handleCopy() {
if (iframe?.contentDocument) {
// 获取dom元素
const document = iframe.contentDocument;
// 获取当前页码元素
const pageNumberEle = document.getElementById(
"pageNumber"
) as HTMLInputElement;
// 获取当前页码
const pageNumber = pageNumberEle.value;
// 获取当前页元素
const page = document.querySelector('.page[data-page-number=11]');
// 获取当前页文本内容
const textContent = page?.querySelector(".textLayer")?.textContent || "";
// 复制到剪切板的代码
console.log("textContent", textContent);
// 将选定的文本保存到剪贴板
navigator.clipboard.writeText(textContent);
}
}