<template> <div class="pdf" v-show="fileType === 'pdf'"> <p class="arrow"> // 上一頁 <span @click="changePdfPage(0)" class="turn" :class="{grey: currentPage==1}">Preview</span> {{currentPage}} / {{pageCount}} // 下一頁 <span @click="changePdfPage(1)" class="turn" :class="{grey: currentPage==pageCount}">Next</span> </p> // 自己引入就可以使用,這里我的需求是做了分頁功能,如果不需要分頁功能,只要src就可以了 <pdf :src="src" // src需要展示的PDF地址 :page="currentPage" // 當前展示的PDF頁碼 @num-pages="pageCount=$event" // PDF文件總頁碼 @page-loaded="currentPage=$event" // 一開始加載的頁面 @loaded="loadPdfHandler"> // 加載事件 </pdf> </div> </template>
import pdf from 'vue-pdf' export default { components: {pdf}, data () { return { currentPage: 0, // pdf文件頁碼 pageCount: 0, // pdf文件總頁數 fileType: 'pdf', // 文件類型
src: '', // pdf文件地址
} },
created: {
// 有時PDF文件地址會出現跨域的情況,這里最好處理一下
this.src = pdf.createLoadingTask(this.src)
} method: { // 改變PDF頁碼,val傳過來區分上一頁下一頁的值,0上一頁,1下一頁 changePdfPage (val) { // console.log(val) if (val === 0 && this.currentPage > 1) { this.currentPage-- // console.log(this.currentPage) } if (val === 1 && this.currentPage < this.pageCount) { this.currentPage++ // console.log(this.currentPage) } }, // pdf加載時 loadPdfHandler (e) { this.currentPage = 1 // 加載的時候先加載第一頁 } } } </script>
實際效果
問題補充: 文件打印亂碼問題解決方法
之前有人問了關於PDF打印亂碼問題,我自己試了確實有這個問題,在官網找了一下,有人提交了代碼解決了這個問題,現在我把方法附上
原始的打印頁面,PDF格式亂碼,主要是因為PDF里使用了自定義字體,不能識別
需要修改vue-pdf安裝包的pdfjsWrapper.js文件
上面后綴為1的文件是原始的,紅線框起來的是我修改之后的文件
替換之后,打印就能正常顯示了,
博客園貌似不能上傳文件,代碼太多就不放上來了,如果有需要可以找我郵箱發你,或者到官網自己修改文件
git-hup地址:https://github.com/FranckFreiburger/vue-pdf/pull/130/commits/253f6186ff0676abf9277786087dda8d95dd8ea7,
上面提供的解決文件打印亂碼的問題,實現起來比較麻煩,而且現在vue-pdf的版本已經更新了,用這個方法可能還會出現空白頁的問題.自己在研究了下,用了iframe來預覽打印,效果會更好些,這里把方法放上來,有需要的可以試試
這里的例子是把PDF文件放在elment的彈框中,當然你可以根據你自己的適用場景來決定
html:
<el-dialog :close-on-click-modal="false" :visible.sync="dialogVisible" :fullscreen="true" title="文件預覽"> <div class="agreement_picture"> <div class="pdf"> <!-- <pdf // 之前的用PDF插件的方法 v-for="i in pdf.numPages" :key="i" :page="i" :src="src"> </pdf> --> // 使用iframe方法 <iframe :src="src" frameborder="0" style="width: 100%; height: 100%"></iframe> </div> </div> <span slot="footer" class="dialog-footer"> <div class="tip-left transfer"> <el-button type="info" @click="dialogVisible=false">不同意</el-button> <el-button type="danger" @click="agreeSignFun">同意</el-button> </div> </span> </el-dialog>
js:
data () { return { src: '/static/file/中國互聯網整體網民發展狀況——《第31次中國互聯網發展狀況調查報告(上)》.pdf', //pdf地址,這里我用的是我本地的文件,你也可以使用后台的文件
dialogVisible: true } }
效果展示:
打印效果:
補充內容:
朋友們,關於跨域問題,我這里說明一下,如果你是在本地localhost環境請求后台接口返回的文件地址,一般都會跨域,報錯如下
這個文件地址我在瀏覽器可以直接打開預覽
遇到這種問題,是因為你本地的localhost和你后台返回的域名不一致,可以先用一個本地靜態文件調試效果,在線上環境即通過打包部署的環境(域名和返回的PDF域名一致的環境)再看效果.如果域名端口一致的情況還有報跨域的錯誤,那你的項目與vue-pdf八字不合,建議更換組件
另外補充一下打印的問題,通過vue-pdf自帶的打印功能,打印出來的效果一般是這樣
這個作者在git上也說了,現在vue-pdf的打印功能還在試驗階段,沒有完善,所以寄希望於這個方法實現打印還需一段時日,上面的內容里我用了<iframe>標簽來預覽打印,但是現在iframe已經不怎么使用了,有些項目還不允許用,這里我再補充兩種打印方法
1. 先把PDF內容轉成圖片后再打印
<el-dialog title="文件預覽" :visible.sync="dialogVisible" width="50%" > <div ref="printContent"> <!-- 加載全部頁面的PDF是循環生成,不能指定ref,不能調用print打印方法 --> <Pdf v-for="i in numPages" :key="i" :src="src" :page="i" /> <!-- 寫一個隱藏的PDF,用來調用打印 --> <Pdf v-show="false" ref="printPdf" :src="src" /> </div> <span slot="footer" class="dialog-footer"> <el-button @click="print">vue-pdf自帶打印</el-button> <el-button type="primary" @click="toImg">轉圖片打印</el-button> </span> </el-dialog>
<script> import Pdf from 'vue-pdf' import html2canvas from 'html2canvas' import printJS from 'print-js' export default { components: { Pdf }, data() { return { fileList: [ { id: 1, fileName: '增進函', fileUrl: 'http://172.16.79.33:8888/group1/.........../rBBPIV7whg2AQNCmAAoc6DKtkwE841.pdf' }, { id: 2, fileName: '應收賬款', fileUrl: `${window.location.origin}/test1.pdf` } ], numPages: undefined, dialogVisible: false, src: '', printName: '轉圖片打印' } }, created() { }, methods: { // 預覽 preview(item) { this.src = Pdf.createLoadingTask(item.fileUrl) this.src.promise.then(pdf => { this.numPages = pdf.numPages }) this.dialogVisible = true this.printName = item.fileName }, // 轉圖片打印 toImg() { html2canvas(this.$refs.printContent, { backgroundColor: null, useCORS: true, windowHeight: document.body.scrollHeight }).then((canvas) => { const url = canvas.toDataURL() printJS({ printable: url, type: 'image', documentTitle: this.printName }) // console.log(url) }) }, // pdf自帶打印 print() { this.$refs.printPdf.print() } } }
打印效果
2.跳轉頁面打印,這種和iframe的差不多,新建一個頁面,調用window.print()打印頁面,效果如下
最近我會把vue-pdf的使用整理一下,把源碼放到git上,之前的代碼找不到了
如果以上都不能解決你的問題,我覺得你可以使用window.open()直接新頁面打開預覽,使用瀏覽器自帶的打印預覽功能.如果產品不同意,你可以對他曉之以情,動之以理
現在一般項目為了安全性,不會直接返回文件地址,會返回文件流的格式,對於文件流格式文件可以轉化成blob文件,如果有需要可以看下我另一篇博客:文件流數據如何轉blob文件 https://www.cnblogs.com/steamed-twisted-roll/p/11821148.html