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文件,最后導致某些機型無法正常渲染。如下圖所示
這里有個小點: 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個
- 這個組件在打包上線后,會無法正常加載出來,導致對應(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)配置了。
這個過程解決兼容問題,費時費力,還以為無法解決了,不過皇天不負苦心人,這個問題還是被解決了,所以記錄下。
后續(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>當前信息無法加載,您可以<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鏈接會導致頁面白屏,微信、安卓不會
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-03
vue之el-tree懶加載數(shù)據(jù)并且實現(xiàn)樹的過濾問題
這篇文章主要介紹了vue之el-tree懶加載數(shù)據(jù)并且實現(xiàn)樹的過濾問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-04-04
vue3中g(shù)etCurrentInstance不推薦使用及在<script?setup>中獲取全局內(nèi)容的三種方式
這篇文章主要給大家介紹了關(guān)于vue3中g(shù)etCurrentInstance不推薦使用及在<script?setup>中獲取全局內(nèi)容的三種方式,文中通過介紹的非常詳細,對大家的學習或者工作具有一定的參考借鑒價值,需要的朋友可以參考下2024-02-02

