Electron PDF.js 预览文档问题解决

使用 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);
    }
}
相关推荐
爱吃羊的老虎11 分钟前
【WEB开发.js】getElementById :通过元素id属性获取HTML元素
前端·javascript·html
妙哉73627 分钟前
零基础学安全--HTML
前端·安全·html
咔叽布吉34 分钟前
【前端学习笔记】AJAX、axios、fetch、跨域
前端·笔记·学习
GISer_Jing1 小时前
Vue3常见Composition API详解(适用Vue2学习进入Vue3学习)
前端·javascript·vue.js
Dragon Wu1 小时前
TailwindCss 总结
前端·css·前端框架
bpmf_fff1 小时前
十、事件类型(鼠标事件、焦点.. 、键盘.. 、文本.. 、滚动..)、事件对象、事件流(事件捕获、事件冒泡、阻止冒泡和默认行为、事件委托)
前端·javascript
泰山小张只吃荷园1 小时前
期末Python复习-输入输出
java·前端·spring boot·python·spring cloud·docker·容器
悦涵仙子2 小时前
vueuse中的useTemplateRefsList
前端·javascript·vue.js
萧萧玉树2 小时前
分布式在线评测系统
前端·c++·后端·负载均衡
haima952 小时前
ubuntu安装chrome无法打开问题
前端·chrome