vue 使用 vue-pdf 實現pdf在線預覽


之前的demo增加了圖片預覽,於是今天下午追完番劇就突然想到能不能把pdf在線預覽也做了,說干就干,剛開始查了很多教程,我發現很多人都在說什么pdf.js這個庫,這當然沒什么問題,pdf.js的確可以非常完美的實現pdf在線預覽的過程,但是感覺這樣直接進去有點不太優雅,於是找找看看有沒有什么現成的組件,發現有vue-pdf這個組件,雖然說它沒有原生那樣強大,比如不支持pdf文字復制,打印會亂碼,但是我感覺已經足以滿足我的需求了。本篇筆記循序漸進,從基礎的demo,到一個可用的程度,文末列出了大家在實際使用的過程中可能會遇到的問題和解決方案。

安裝:

這個沒有啥背景知識可講,我們直接跳到安裝環節,vue-pdf 和其他vue組件的安裝並無不同,打開命令行,敲入:

npm install --save vue-pdf
復制代碼

注意路徑。別在桌面調出來個終端安裝了,這種直接打回去重學Vue。

vue-pdf 初體驗:

安裝完之后,使用vue-pdf非常簡單,和其他的組件並沒有什么不同,上代碼:

首先我們需要引入這個組件:

<script> import pdf from 'vue-pdf' export default { components:{ pdf }, data(){ return { url:"http://storage.xuetangx.com/public_assets/xuetangx/PDF/PlayerAPI_v1.0.6.pdf", } } </script> 復制代碼

然后在頁面使用vue-pdf,只需要添加標簽:

<template> <div> <pdf ref="pdf" :src="url"> </pdf> </div> </template> 復制代碼

重啟你的項目,訪問這個界面,你大概率會發現pdf已經成功顯示在你的界面上了。這沒有任何問題,但是,正當你准備拿起一根煙,點上,伴着舒適的《美麗的梭羅河》,欣賞你成功的傑作的時候,你會發現,我擦,為啥只有一頁,當玻璃杯碰在一起,滿世界都是夢破碎的聲音。

所以,這只是初體驗,如果你的pdf只有一頁,這樣寫當然沒什么問題,但是當我們呢pdf 有很多頁的時候,你會發現,這行不通了。所以,接下來,我們來看看怎么讓它顯示多頁。

vue-pdf 漸入佳境:

其實,想要顯示多頁也沒那么復雜,你每次就顯示一頁,我,直接v-for 循環,直接顯示完,簡單粗暴。

頁面代碼:

<template> <div> <pdf v-for="i in numPages" :key="i" :src="url" :page="i"></pdf> </div> </template> <script> import pdf from 'vue-pdf' export default { components: { pdf }, data(){ return{ url: '', numPages:1, } }, mounted: function() { this.getNumPages("http://storage.xuetangx.com/public_assets/xuetangx/PDF/PlayerAPI_v1.0.6.pdf") }, methods: { getNumPages(url) { var loadingTask = pdf.createLoadingTask(url) loadingTask.then(pdf => { this.url = loadingTask this.numPages = pdf.numPages }).catch((err) => { console.error('pdf加載失敗') }) }, } } </script> 復制代碼

各個屬性:

  • url :pdf 文件的路徑,可以是本地路徑,也可以是在線路徑。
  • numPages : pdf 文件總頁數。

getNumPages 計算總頁數,順便給url和numPages賦值。

唯一需要大家注意的是這句:

this.getNumPages("http://storage.xuetangx.com/public_assets/xuetangx/PDF/PlayerAPI_v1.0.6.pdf") 復制代碼

注意啊,這句不一定非要寫到mounted里面,你想寫哪就寫哪,比如你前端請求后端,后端返回一個pdf 的url,在那里寫就行,寫在你需要的地方。

vue-pdf 輕車熟路:

很多人看到這,就這,就這?萬一,我pdf有一千頁,我瀏覽器還不得裂開,我追求的是那種在微醺的下午,一頁一頁的翻看的感覺,你能給我嗎?

我不能,才怪,保證滿足你。

<template> <div> <div class="tools"> <bk-button :theme="'default'" type="submit" :title="'基礎按鈕'" @click.stop="prePage" class="mr10"> 上一頁</bk-button> <bk-button :theme="'default'" type="submit" :title="'基礎按鈕'" @click.stop="nextPage" class="mr10"> 下一頁</bk-button> <div class="page">{{pageNum}}/{{pageTotalNum}} </div> <bk-button :theme="'default'" type="submit" :title="'基礎按鈕'" @click.stop="clock" class="mr10"> 順時針</bk-button> <bk-button :theme="'default'" type="submit" :title="'基礎按鈕'" @click.stop="counterClock" class="mr10"> 逆時針</bk-button> </div> <pdf ref="pdf" :src="url" :page="pageNum" :rotate="pageRotate" @progress="loadedRatio = $event" @page-loaded="pageLoaded($event)" @num-pages="pageTotalNum=$event" @error="pdfError($event)" @link-clicked="page = $event"> </pdf> </div> </template> 復制代碼

接下來,我們一一介紹這些都是個啥。

參數介紹:

  • page: 當前顯示的頁數,比如第一頁page=1
  • rotate : 旋轉角度,比如0就是不旋轉,+90,-90 就是水平旋轉。
  • progress :當前頁面的加載進度,范圍是0-1 ,等於1的時候代表當前頁已經完全加載完成了。
  • page-loaded :頁面加載成功的回調函數,不咋能用到。
  • num-pages :總頁數
  • error :加載錯誤的回調
  • link-clicked:單機pdf內的鏈接會觸發。

其他:

  • print 這個是打印函數。 注意:谷歌瀏覽器會出現亂碼,這個和字體有關系。

來,js代碼走一個:

<script>
	import pdf from 'vue-pdf'
	export default {
		name: 'Home',
		components: {
			pdf
		},
		data() {
			return {
				url: "http://storage.xuetangx.com/public_assets/xuetangx/PDF/PlayerAPI_v1.0.6.pdf",
				pageNum: 1,
				pageTotalNum: 1,
				pageRotate: 0,
				// 加載進度
				loadedRatio: 0,
				curPageNum: 0,
			}
		},
		mounted: function() {},
		methods: {
            // 上一頁函數,
			prePage() {
				var page = this.pageNum
				page = page > 1 ? page - 1 : this.pageTotalNum
				this.pageNum = page
			},
            // 下一頁函數
			nextPage() {
				var page = this.pageNum
				page = page < this.pageTotalNum ? page + 1 : 1
				this.pageNum = page
			},
            // 頁面順時針翻轉90度。
			clock() {
				this.pageRotate += 90
			},
            // 頁面逆時針翻轉90度。
			counterClock() {
				this.pageRotate -= 90
			},
            // 頁面加載回調函數,其中e為當前頁數
			pageLoaded(e) {
				this.curPageNum = e
			},
            // 其他的一些回調函數。
			pdfError(error) {
				console.error(error)
			},
		}
	}
</script>
復制代碼

其他騷操作:

// 打印全部 pdfPrintAll() { this.$refs.pdf.print() }, // 打印指定部分 pdfPrint() { this.$refs.pdf.print(100, [1, 2]) }, 復制代碼

具體樣式什么的我就不貼出來了,這些都不是重點,完全可以改成自己喜歡的。

成品展示:

 

 

其他問題以及解決方案:

如何加載本地pdf文件(2020.4.27更新):

評論區有人提到了這個問題,我今天中午的時候試了一下,完全是可以的,但是需要我們做一下本地配置flie-loader才行,否則webpack無法編譯pdf類型的文件,配置方法也很簡單,在項目根目錄新建一個vue.config.js文件,我發現很多人直接就去babel.config.js這個文件里面配置,這樣是不對的,肯定會報錯,

先安裝file-loader:

npm install --save file-loader
復制代碼

然后在vue.config.js中加入以下內容:

module.exports = { chainWebpack: config => { const fileRule = config.module.rule('file') fileRule.uses.clear() fileRule .test(/\.pdf|ico$/) .use('file-loader') .loader('file-loader') .options({ limit: 10000, }) }, publicPath: './' } 復制代碼

之后再url:require("../assets/1.pdf")就沒有任何問題了,注意,vue-pdf src接收的是string對象,如果直接傳url我這里報錯了,你可能需要傳url.default一下。

跨域問題:

網上用pdf.js 很多都會遇到跨域問題,這個我今天實際應用到自己的項目里面了,由於我服務端設置了跨域,所以沒有出現跨域的問題,如果出現跨域需要修改你后端的請求頭。

打印界面字符亂碼:

這個我倒是碰到了,谷歌瀏覽器打印的時候,預覽界面真的變成了 真·方塊字 ,全是方塊。這個問題是因為你pdf中使用了自定義字體導致的,具體解決方案如下:

首先,找到這個文件:node_modules/vue-pdf/src/pdfjsWrapper.js

然后根據github上這個issue,其中紅色的是要刪掉的,綠色的是要加上去的,照着改就可以解決了。

地址: github.com/FranckFreib…

根據我的實際測試,是可以解決打印亂碼的問題的。

非常感謝能讀到這里的朋友,你們的支持和關注是我堅持高質量分享下去的動力。

相關代碼和文檔已經上傳至本人github。一定要點個star啊啊啊啊啊啊啊

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM