vue3项目中使用pdfjs-dist踩坑记录

有这么一个需求,要求打开pdf文件实现预览,分页跳转、搜索关键字。期望效果如下:
在这里插入图片描述
经过一番调研选择使用pdfjs-dist来完成这一功能。

第一种方案:使用npm在项目中安装pdfjs-dist

npm install pdfjs-dist

执行安装文件报错了,应该是node版本不兼容,到https://www.npmjs.com/上找往期版本,查了一些评论,评价2.16.105版本兼容性好,安装试一下。

npm i pdfjs-dist@2.16.105

在代码中引入

<template>
  <Modal
    v-model="visible"
    fullscreen
    footer-hide
    @on-cancel="cancel"
  >
    <div id="pdf-view">
      <canvas v-for="page in state.pdfPages" :key="page" id="pdfCanvas" />
      <div id="text-view"></div>
    </div>
  </Modal>
</template>
<script>
    import * as pdfjsViewer from 'pdfjs-dist/web/pdf_viewer.js'
    import 'pdfjs-dist/web/pdf_viewer.css'
    import * as PDF from 'pdfjs-dist'
    PDF.GlobalWorkerOptions.workerSrc = '/pdf.worker.js'
    const pdf = 'http://www.nhc.gov.cn/sps/s7887k/202301/0e55a01df50c47d9a4a43db026e3afc3/files/63f752a17cfd4b4781f744477561866f.pdf'
    let pdfDoc = null;
    export default {
        data () {
            return {
                state: {
                    // 文件路径
                    pdfPath: pdf,
                    // 总页数
                    pdfPages: 1, 
                    // 页面缩放
                    pdfScale: 1, 
                },
                visible: false,

            }
        },
        mounted () {
            // this.loadFile(this.state.pdfPath)
        },
        methods: {
            init () {
                this.visible = true
                this.loadFile(this.state.pdfPath)
            },
            cancel () {
                this.visible = false
            },
            loadFile(url) {
                PDF.getDocument({
                    url,
                    cMapUrl: 'https://cdn.jsdelivr.net/npm/pdfjs-dist@2.16.105/cmaps/',
                    cMapPacked: true,
                }).promise.then((pdf) => {
                    pdfDoc = pdf
                    // 获取pdf文件总页数
                    this.state.pdfPages = pdf.numPages
                    this.$nextTick(() => {
                        this.renderPage(1) // 从第一页开始渲染
                    })
                })
            },
            renderPage(num) {
                pdfDoc.getPage(num).then((page) => {
                    const canvas = document.getElementById('pdfCanvas')
                    const ctx = canvas.getContext('2d')
                    const viewport = page.getViewport({ scale: this.state.pdfScale })
                    canvas.width = viewport.width
                    canvas.height = viewport.height
                    const renderContext = {
                        canvasContext: ctx,
                        viewport
                    }
                    page.render(renderContext)
                })
            }
        }
    }
</script>

引入的过程中发生了报错
在这里插入图片描述
原因是需要在引入 pdf is-dist 之后配置 workerSrc,但是引入 pdf is-dist/bui1d/pdf. worker.entry之后浏览器还是有个警告:Warning;Settingup fake worker.,几方查找原来是pdf.workerjs必须位于自己的文件中(而不是与pdfjs捆绑在起)。否则它不能在服务工作线程中运行。
解决方式:将 pdfis-dist/bui1d/pdf.worker.is 复制一份放到项目 public 目录下

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

能够预览但是不是想要的效果,貌似这种只能实现pdf预览功能,而我想要的是官方演示的那种带各种操作的效果。

第二种方法:直接将预构建版本放入public文件夹下使用viewer.html

在这里插入图片描述
下载,解压到public文件夹下。
在这里插入图片描述
使用

// 直接在新窗口中打开
window.open(`/pdfjs-2.5.207-dist/web/viewer.html?file=${pdfurl}`, '_blank')

在这里插入图片描述
找到pdfjs-2.5.207-dist/web/wiewer.js
在这里插入图片描述
效果如下,有个bug,打开pdf文件以后,分页数字会被缓存,下次再打开,会停留在这个页面,如果想回到第1页,需要做一下处理。
在这里插入图片描述
在这里插入图片描述

上面这个方法只能禁用本地对跨域的检查,如果引用的pdf文件地址是外链,依然会报跨域问题,如果对pdf的来源不能确定是不太好解决的。
在这里插入图片描述
上面这种跨域限制,就需要后端介入处理了。
如果产品只是要预览pdf文件,可以用第一种方法或者在新窗口打开pdf文件查看。

window.open(pdfurl, '_blank')

在浏览器的新窗口打开查看pdf文件,没有跨域问题,遗憾的是显示效果不能控制。先记到这儿吧,后期如果有更好的解决跨域方案再来更新。

参考链接

Vue3 项目使用 `pdfjs-dist` 时,若需兼容旧版浏览器(如不支持较新 JavaScript 特性的浏览器),可能会遇到 `Promise.withResolvers is not a function` 的错误。该问题源于 `pdfjs-dist` 的较新版本依赖于现代浏览器特性,例如 `Promise.withResolvers()`,而这一特性尚未广泛支持[^4]。 ### 解决方案 #### 1. 使用兼容性更好的 `pdfjs-dist` 版本 可以通过安装一个已知兼容性较好的 `pdfjs-dist` 版本来避免此问题。具体操作如下: ```bash npm uninstall pdfjs-dist npm install pdfjs-dist@2.12.313 ``` 这个版本经过测试,在多数旧版浏览器上表现良好,并且不会引入对 `Promise.withResolvers` 的依赖[^3]。 #### 2. 添加 Polyfill 补丁文件 如果必须使用较新的 `pdfjs-dist` 版本,则可以手动添加一个 Polyfill 来模拟 `Promise.withResolvers` 功能。在项目入口文件或初始化脚本中加入以下代码: ```javascript if (typeof Promise.withResolvers === &#39;undefined&#39;) { Promise.withResolvers = function () { let resolve, reject; const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); return { promise, resolve, reject }; } } ``` 这段代码会检查当前运行环境是否支持 `Promise.withResolvers`,如果不支持则手动实现它,以确保相关功能能够正常运行[^2]。 #### 3. 配置构建工具处理兼容性问题 虽然 Vite 提供了 `@vitejs/plugin-legacy` 插件用于兼容旧版浏览器,但由于报错代码存在于 `node_modules` 中,因此无法通过标准的 Babel 转换进行修复。然而,仍然可以尝试配置构建工具(如 Webpack 或 Rollup)以更好地支持旧版浏览器。 #### 4. 使用 Legacy 构建路径 对于某些版本的 `pdfjs-dist`,可以通过引入其 `legacy` 构建版本来绕过兼容性问题: ```javascript import * as workerSrc from "pdfjs-dist/legacy/build/pdf.worker.min?url"; ``` 相较于原版代码: ```javascript import * as workerSrc from "pdfjs-dist/build/pdf.worker.min?url"; ``` 这种方式可以直接引用更兼容的构建输出,从而避免因新语法导致的运行时错误[^4]。 ### 总结 为了解决 Vue3 项目中 `pdfjs-dist` 的兼容性问题,推荐优先降级到已知兼容性良好的版本(如 `2.12.313`)。如果需要使用新版功能,则应结合 Polyfill 和适当的构建配置,以确保在旧版浏览器中的稳定运行。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sherry Tian

打赏1元鼓励作者

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值