1.背景
后臺返回了一個在線的pdf地址,需要我這邊去做一個pdf的預覽(需求1),并且支持配置是否可以下載(需求2),需要在當前頁就能預覽(需求3)。之前我寫過一篇預覽pdf的文章,但是當時后臺返回的是blob流文件,如果你們的pdf也是以流文件的形式返回的,可以看這篇文章(超鏈接點進去就行)。
2.簡單說下pdf預覽的實現方式
a.借助 <embed> / <iframe>標簽
這個是真的很簡單,我直接貼在下面了,缺點是: 沒辦法阻止用戶打印和下載pdf,所以我pass了這個方案
<embedtype="application/pdf":src="pdfUrl"width="800"height="600" /><iframe:src="pdfUrl"width="800"height="600" />
實現效果:
b.使用vue插件vue-pdf來渲染(應該還有一些其他的插件也可以使用,大家自己研究下實現的效果把)
這個方案我已經試了且用到項目上了,但是感覺很丑,跟瀏覽器打開pdf的效果差別很大,原因是這個插件大概得原理是把pdf轉成了圖片然后使用canvas來渲染的,然后很多東西都沒有,就被我pass了。你可以想象一下你的pdf,然后你截圖放進你網頁上的感覺,就差不多是這個效果了,圖片我忘記保存了,大家腦補一下
我找了個圖,這個其實別人還做了一些其他的渲染,比如下面的也是他自己寫的。我感覺是沒這么好看的,所以就拋棄了這個
c.使用pdf.js預覽
我覺得預覽pdf這一塊還是得用pdf.js,真的很成熟,樣式也還是很給力的,然后想要改成什么樣就可以改成什么樣,因為源碼在你手上。
缺點:稍微麻煩點,需要處理跨域的問題(但是如果你的網站、pdf文件所在位置,后臺返回的pdf位置都在同一個域名下的話,就不需要處理)。且可能需要知道一點運維的知識,不然很可能你在本地能運行成功,但是到線上可能訪問不到
3.使用pdf.js預覽pdf
a.到官網去下載pdf.js
建議下第二個!!!(別問我為啥,因為我下了第一個來寫demo發現有報錯,又踩坑了)
b.解壓之后直接丟到項目中的public文件夾下面去
c.寫一個pdf.vue文件,內容如下(注意我的路徑,這個路徑跟public的路徑是一樣的,前面加了一個/,原因如下:當我們使用npm run serve時,我們的本地電腦也會開啟一個服務將public項目中的資源開發出來,此時跟服務器是一樣的,你去訪問:localhost:8080/pdf/web/viewer.html 是可以正常訪問通的,這里不理解的話,就依葫蘆畫瓢吧,沒關系的 ):
<template><iframe :src="'/pdf/web/viewer.html?file='+pdfUrl"></iframe>
</template>
<script>export default {name: 'Pdf',props: {pdfUrl: {type: String,default: ''}}
}
</script><style scoped>
iframe {/* width: 960px; */width: 1100px;max-width: 100%;height: 800px;margin-left: 50%;transform: translateX(-50%);
}
</style>
d.在頁面中導入使用:
<template><div class="home"><div>這下面是我用來預覽pdf文件的</div><pdf :pdfUrl="pdfUrl"></pdf></div>
</template><script>
import pdf from './pdf.vue';export default {name: 'HomeView',components:{pdf},data() {return {pdfUrl:'http://localhost:8080/怎么刪除wps中最后的空白頁.pdf'}},created(){},
};
</script>
e.預覽效果是這樣子的
f.到源碼中修改一下把打印和下載都去掉,這一步很簡單,大家自己去弄了,也可以直接使用我的pdf文件,我這里都已經改好了。最后的效果如下:
4.難點處理
很大概率你在本地能跑通代碼,但是到線上會出問題,可能會出現的問題我都羅列在下面了
a:線上404
線上404的話,說明你線上的這個pdf的資源沒有上傳到線上,或者線上寫的路徑不對!比如你的ip為192.168.1.182。如果正常的話,你去訪問192.168.1.182/pdf/web/viewer.html 是可以正常訪問通的。如果都沒有出現正常的這個頁面,如下:
那么說明你pdf文件資源沒上傳或者你寫的路徑不對。 1.檢查dist包里面是否有這個pdf文件(一般放在public文件夾的都會原封不動的打到dist包中,這里還是需要檢查下) 2.如果發現有的話,說明沒問題,那么你需要到服務器上看下有沒有這個pdf文件上傳上去了沒有。如果有的話,那就是你寫的路徑不對,或者是后臺沒有開發這個靜態資源文件夾。此時如果你不懂的話,你就跟后臺說下你要去訪問這個頁面,應該要用什么路徑去訪問才能訪問的到。正常來說 192.168.1.182/pdf/web/viewer.html是可以的,如果不可以,可能是要加什么路徑,比如192.168.1.182/web/pdf/web/viewer.html這種。如果你是web/pdf/web/viewer.html才能訪問的到,那么你就要在你的pdf.vue里面改下路徑以對應生產環境
b:線上顯示資源跨域
這里是很明顯從瀏覽器面板能看到的。這個的處理,需要你和后臺一起處理,首先你訪問/pdf/web/viewer.html這個的地址和你訪問的頁面的地址是需要在一個域名下的(如果不在的話,需要后臺處理,開放個別域名),第二點,就是/pdf/web/viewer.htmlfile='+pdfUrl" 這個pdfUrl的地址最好也是跟你的pdf的viewer.html在同一個域名下,相當于三個都在同一域名下,就不會有跨域問題了。如果后臺說是靜態資源都放到另一臺主機上了,那么麻煩他讓他做個資源映射,保證你的pdfUrl是跟你的pdf的viewer.html在同一個域名下的
5.demo地址
demo地址可下載自己看代碼:https://github.com/rui-rui-an/viewpdf
參考文章:https://juejin.cn/post/7207078219215732794?searchId=2024060423581130C1D707D73A6338E3BA#heading-14
6.更新
關于下載(忘記寫下載了)
html:
我這里用的是一個div,然后文件名作為用戶下載的入口,點擊就能去下載
<div class="downpdf" href="#" v-if="is_download" @click="goDownload">{{ pdfname }}</div>
方法1(直接下載):
downloadPdf(pdfurl) {let fileName = this.pdfnamelet reg = /^([hH][tT]{2}[pP]://|[hH][tT]{2}[pP][sS]://)(([A-Za-z0-9-~]+).)+([A-Za-z0-9-~/])+$/if (!reg.test(pdfurl)) {throw new Error('傳入參數不合法,不是標準的文件鏈接')} else {let xhr = new XMLHttpRequest()xhr.open('get', pdfurl, true)xhr.setRequestHeader('Content-Type', 'application/pdf')xhr.responseType = 'blob'let that = thisxhr.onload = function () {if (this.status == 200) {//接受二進制文件流var blob = this.responsethat.downloadExportFile(blob, fileName)}}xhr.send()}},downloadExportFile(blob, tagFileName) {let downloadElement = document.createElement('a')let href = blobif (typeof blob == 'string') {downloadElement.target = '_blank'} else {href = window.URL.createObjectURL(blob) //創建下載的鏈接}downloadElement.href = hrefdownloadElement.download = tagFileName//下載后文件名document.body.appendChild(downloadElement)downloadElement.click() //點擊下載document.body.removeChild(downloadElement) //下載完成移除元素if (typeof blob != 'string') {window.URL.revokeObjectURL(href) //釋放掉blob對象}},