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);
    }
}
相关推荐
Jinuss3 分钟前
Vue3源码reactivity响应式篇之computed计算属性
前端·vue3
落日沉溺于海3 分钟前
React From表单使用Formik和yup进行校验
开发语言·前端·javascript
知识分享小能手4 分钟前
React学习教程,从入门到精通, React 新创建组件语法知识点及案例代码(11)
前端·javascript·学习·react.js·架构·前端框架·react
会豪7 分钟前
工业仿真(simulation)--前端(五)--标尺,刻度尺
前端
会豪9 分钟前
工业仿真(simulation)--前端(四)--画布编辑(2)
前端
an__ya__11 分钟前
Vue数据响应式reactive
前端·javascript·vue.js
苦逼的搬砖工14 分钟前
Flutter UI Components:闲来无事,设计整理了这几年来使用的UI组件库
前端·flutter
想买Rolex和Supra的凯美瑞车主16 分钟前
Taro + Vite 开发中 fs.allow 配置问题分析与解决
前端
ruanCat17 分钟前
使用 vite 的 base 命令行参数来解决项目部署在 github page 的路径问题
前端·github
Codebee22 分钟前
使用Qoder 改造前端UI/UE升级改造实践:从传统界面到现代化体验的华丽蜕变
前端·人工智能