Vue2項目如何使用pdfjs-dist解析pdf
先說結(jié)論
使用pdfjs-dist的2.7.570版本
使用pdfjs-dist的2.7.570版本的es5產(chǎn)物,該版本的es5的build產(chǎn)物沒有特殊寫法,對vue.config.js、babel.config.js的兼容性最好,不需要額外再下載其他插件,比如可選鏈插件等
引用方式
import * as pdfjsLib from 'pdfjs-dist/es5/build/pdf' import pdfWorker from 'pdfjs-dist/es5/build/pdf.worker.entry' pdfjsLib.GlobalWorkerOptions.workerSrc = pdfWorker pdfjsLib.GlobalWorkerOptions.isEvalSupported = false // 關(guān)閉 eval 支持(防止漏洞)
背景
某天,產(chǎn)品同事發(fā)現(xiàn)C端的資質(zhì)展示頁面(H5)的圖片渲染有問題,經(jīng)排查發(fā)現(xiàn)有些鏈接是.pdf結(jié)尾的pdf文件,最后導(dǎo)致某些機型無法正常渲染。如下圖所示
這里有個小點: ios機型會把pdf渲染出來1頁,安卓機型無法渲染pdf
遇到問題時的思考
這種情況在線上是否多,如果量級不多,個人感覺可以嘗試后端進行解析PDF轉(zhuǎn)成圖片,在更新數(shù)據(jù)庫。但這需要結(jié)合業(yè)務(wù)系統(tǒng)來看,因為這是“資質(zhì)文件”,所以得保證業(yè)務(wù)系統(tǒng)在這方面的功能是怎么樣的,是只能上傳圖片還是pdf,還是都能,不過這是后面分析才得到的結(jié)果
后端是否好解決,這需要和后端溝通
需求
能夠根據(jù)pdf鏈接展示出他的所有頁數(shù)內(nèi)容,不失真,能在各個機型的web-view中運行,如安卓app、ios的app、支付小程序、微信小程序。
只做pdf解析預(yù)覽功能,不需要額外功能,把內(nèi)容轉(zhuǎn)成圖片即可。
盡量做到不修改vue.config.js、babel.config.js來解決這個問題,理想情況就是新增一個組件,然后對應(yīng)頁面判斷是鏈接,最后使用下就好了。畢竟這是老項目,這些可不能亂動。
前期開發(fā)工作
與后端溝通,結(jié)果是后端不好解決,只能交給前端來解決
先問gpt,具體方案和關(guān)鍵依賴,可能的坑點
搜索gpt,根據(jù)得到的關(guān)鍵依賴(pdfjs-dist
),了解他的issue、坑點、demo等
順便搜下相關(guān)文章,但發(fā)現(xiàn)質(zhì)量都挺一般的,數(shù)量有點少,于是就參考gpt的,其次就是pdfjs-dist
的文檔有點難看懂
具體實施
下載 pdfjs-dist
,下載時下的是最新版本,5.x.x
新建pdf-viewr.vue
組件
復(fù)制gpt給我的代碼
運行項目
# gpt給的案例 import * as pdfjsLib from 'pdfjs-dist/build/pdf' import pdfWorker from 'pdfjs-dist/build/pdf.worker.entry' pdfjsLib.GlobalWorkerOptions.workerSrc = pdfWorker // 解析過程省略,主要核心是引用方式的問題
踩坑之旅
依照上述實施行為,結(jié)果就是直接報錯,運行不了,于是我就開始了我的漫長踩坑之旅
我的依賴&版本
- node: 12.22.22
- @vue/cli: ^3.12.0
- babel-core: 7.0.0-bridge.0
- vue: 2.6.x
版本問題
使用pdfjs-dist遇到了非常多的版本兼容性問題,由于用的是最新版本,有很多寫法,和我的對不上,于是我的想法是降版本,但一開始不知道降到多少,畢竟有1549個版本,想法是問ai,但ai回答出來的版本還是不太行,于是我就打算換個方式,找找有沒有現(xiàn)成的封裝好的組件
這里找到的是vue-pdf
,這個組件是用pdfjs-dist
+vue2
的,我大喜過望,馬上下載使用,寫起來很快呀,但新的問題已然埋下
vue-pdf問題
- issue數(shù)量特別多,只能說慎用,一共235個
- 這個組件在打包上線后,會無法正常加載出來,導(dǎo)致對應(yīng)頁面白屏。根據(jù)gpt的說法是可能丟失了pdfjs-dist,然后我就去找原因,這種情況先找issue,我在vue-pdf的issue中看到了有人遇到了同樣的問題,然后我在某個issue中,看到了這么一句話:使用2.7.570版本。
于是我順藤摸瓜,找到pdfjs-dist的版本記錄,找到他的內(nèi)容是什么,然后我就發(fā)現(xiàn)了一個讓我很興奮的點:
這個依賴的有build和es5的build產(chǎn)物!?。?,這是最關(guān)鍵的,他的其他版本我看了幾個,我發(fā)現(xiàn)沒有es5的打包產(chǎn)物
用build的產(chǎn)物仍然存在特殊寫法,比如可選鏈,因為我的項目沒有可選鏈的babel插件,所以仍然不能用
但是es5的產(chǎn)物沒有特殊寫法,所以理論上用這個就能解決了,因為引用報錯的問題是語法相關(guān)的兼容性問題,我又不想新增babel插件、loader依賴等
最后在我使用了這個版本后,修改了原先AI提供的案例中的引用方式,于是項目正常跑了起來,這里就不使用vue-pdf
了,使用pdfjs-dist
,用它來解析,然后轉(zhuǎn)圖片。
對比如下:
# 前 import * as pdfjsLib from 'pdfjs-dist/build/pdf' import pdfWorker from 'pdfjs-dist/build/pdf.worker.entry' pdfjsLib.GlobalWorkerOptions.workerSrc = pdfWorker # 后 import * as pdfjsLib from 'pdfjs-dist/es5/build/pdf' import pdfWorker from 'pdfjs-dist/es5/build/pdf.worker.entry' pdfjsLib.GlobalWorkerOptions.workerSrc = pdfWorker
病毒問題
病毒問題也是看vue-pdf
的issue才知道的
根據(jù)報告鏈接所提供的方案就是
pdfjsLib.GlobalWorkerOptions.isEvalSupported = false // 關(guān)閉 eval 支持(防止漏洞)
小結(jié)
為了解決pdfjs-dist在vue2的老項目的兼容性問題,最終方案就是使用pdfjs-dist@2.7.570,這樣就不用影響到之前的vue.config.js、babel.config.js相關(guān)配置了。
這個過程解決兼容問題,費時費力,還以為無法解決了,不過皇天不負(fù)苦心人,這個問題還是被解決了,所以記錄下。
后續(xù)計劃
自己打包高版本(5.x.x)的pdfjs-dist來適應(yīng)內(nèi)部項目
研究vue-pdf打包上線白屏問題
接入vue3項目
分頁加載優(yōu)化,大文件優(yōu)化
代碼
pdf解析預(yù)覽組件
<template> <div class="pdf-viewer"> <van-loading v-if="loading" type="spinner" size="32px" vertical>加載中</van-loading> <div v-else> <div v-if="error" class="fallback"> <p>當(dāng)前信息無法加載,您可以<a :href="pdfUrl" target="_blank">點擊查看</a></p> </div> <div v-else> <div v-for="(page, index) in pages" :key="index" class="pdf-page"> <img :src="page" :alt="'pdf ' + (index + 1)" class="pdf-image"> </div> </div> </div> </div> </template> <script> import { Loading } from 'vant' // ? 使用pdfjs-dist的2.7.570版本的es5產(chǎn)物,該版本的es5的build產(chǎn)物沒有特殊寫法,對本項目vue.config.js、babel.config.js的兼容性最好 import * as pdfjsLib from 'pdfjs-dist/es5/build/pdf' import pdfWorker from 'pdfjs-dist/es5/build/pdf.worker.entry' pdfjsLib.GlobalWorkerOptions.workerSrc = pdfWorker pdfjsLib.GlobalWorkerOptions.isEvalSupported = false // 關(guān)閉 eval 支持(防止漏洞)// 漏洞鏈接: https://www.venustech.com.cn/new_type/aqtg/20240514/27492.html export default { name: 'pdf-viewer', props: { pdfUrl: { type: String, required: true, }, }, components: { [Loading.name]: Loading, }, data() { return { pages: [], loading: true, error: false, } }, mounted() { this.loadPdf() }, methods: { async loadPdf() { try { const loadingTask = pdfjsLib.getDocument(this.pdfUrl) const pdf = await loadingTask.promise const pageImages = [] for (let pageNum = 1; pageNum <= pdf.numPages; pageNum++) { const page = await pdf.getPage(pageNum) const viewport = page.getViewport({ scale: 2 }) // scale 調(diào)大可提高清晰度 const canvas = document.createElement('canvas') const context = canvas.getContext('2d') canvas.width = viewport.width canvas.height = viewport.height await page.render({ canvasContext: context, viewport }).promise pageImages.push(canvas.toDataURL()) } this.pages = pageImages this.loading = false } catch (e) { console.error('PDF 加載失敗:', e) this.error = true this.loading = false } }, }, } </script> <style lang="stylus" scoped> .pdf-viewer { width: 100%; overflow-x: hidden; } .pdf-image { width: 100%; display: block; object-fit: contain; } .fallback { text-align: center; color: #999; font-size: 14px; height: 100%; display: flex; justify-content: center; align-items: center; a { color: #007aff; text-decoration: underline; } } </style>
鏈接類型判斷
// 判斷文件類型(擴展名優(yōu)先,fallback 為 HEAD) async detectFileType(url) { // 1. 特殊 scheme 優(yōu)先判斷 if (url.startsWith('data:image/')) return 'image' if (url.startsWith('data:application/pdf')) return 'pdf' if (url.startsWith('blob:')) return 'unknown' // 2. 擴展名判斷(寬松匹配) if (/\.(jpe?g|png|gif|bmp|webp|svg)([\?#].*)?$/i.test(url)) return 'image' if (/\.pdf([\?#].*)?$/i.test(url)) return 'pdf' // 3. 嘗試發(fā) HEAD 請求獲取 content-type try { const res = await axios.head(url) // ? 支付寶小程序如果遇到404鏈接會導(dǎo)致頁面白屏,微信、安卓不會 const contentType = res.headers['content-type'] || '' if (contentType.includes('image/')) return 'image' if (contentType.includes('application/pdf')) return 'pdf' } catch (e) { console.warn('鏈接類型獲取失敗:', url, e.message) } return 'unknown' }
到此這篇關(guān)于Vue2項目如何使用pdfjs-dist解析pdf的文章就介紹到這了,更多相關(guān)Vue2解析pdf內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue登錄頁面回車執(zhí)行事件@keyup.enter.native問題
這篇文章主要介紹了vue登錄頁面回車執(zhí)行事件@keyup.enter.native問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-03-03vue之el-tree懶加載數(shù)據(jù)并且實現(xiàn)樹的過濾問題
這篇文章主要介紹了vue之el-tree懶加載數(shù)據(jù)并且實現(xiàn)樹的過濾問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-04-04vue3中g(shù)etCurrentInstance不推薦使用及在<script?setup>中獲取全局內(nèi)容的三種方式
這篇文章主要給大家介紹了關(guān)于vue3中g(shù)etCurrentInstance不推薦使用及在<script?setup>中獲取全局內(nèi)容的三種方式,文中通過介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考借鑒價值,需要的朋友可以參考下2024-02-02