vue项目中实现预览pdf
1. iframe
<iframe :src="pdfSrc"></iframe>
data() {
return {
pdfSrc: 'http://192.168.0.254:19000/trend/2023/12/27/5635529375174c7798b5fabc22cbec45.pdf',
}
},
iframe {
width: 100%;
height: calc(100vh - 132px - 2 * 20px - 160px);
}
2. vue-pdf
npm i vue-pdf --save-dev
<!--
* @Description: vue-pdf使用
* @Author: mhf
* @Date: 2023-12-28 11:37:30
-->
<template>
<div class="systemDescription">
<div class="systemDescription-header">vue-pdf使用</div>
<lineH style="margin: 20px 0"/>
<div class="systemDescription-pdf">
<pdf
v-for="i in numPages"
:key="i"
:src="pdfSrc"
:page="i"
></pdf>
</div>
</div>
</template>
<script>
import pdf from 'vue-pdf'
export default {
name: 'systemDescription',
components: { pdf },
props: {},
data() {
return {
pdfSrc:
'http://192.168.0.254:19000/trend/2023/12/27/5635529375174c7798b5fabc22cbec45.pdf',
numPages: undefined,
}
},
methods: {},
created() {
},
mounted() {
let src = pdf.createLoadingTask(this.pdfSrc);
src.promise.then(pdf => {
this.numPages = pdf.numPages; // 解决vue-pdf默认只展示第一页的问题
});
}
}
</script>
<style lang="scss" scoped>
.systemDescription {
padding: 50px 30px 40px;
&-header {
font-size: 26px;
font-family: Source Han Sans CN;
font-weight: 700;
color: #333;
text-align: center;
}
&-pdf {
margin: 0 0 0 -24px;
width: calc(100% + 50px);
height: calc(100vh - 132px - 2 * 20px - 180px);
overflow-y: auto;
}
}
</style>
参考:解决vue-pdf默认只展示第一页的问题
使用vue-pdf展示静态PDF文件的时候(在线PDF可使用embed标签查看),常规操作之后发现只能加载第一页PDF,以下是解决方案:
vue-pdf使用过程如下:
$ yarn add vue-pdf
or
$ npm install vue-pdf
在组件中使用:
<template>
<pdf src=""></pdf>
</template>
<script>
import pdf from 'vue-pdf'
exprot default {
component: {
pdf
}
}
</script>
这个时候,多页的PDF只会显示第一页,这时各位可以去查看一下vue-pdf的源码,我们可以发现,它的实现过程是将PDF按页绘制在canvas上的,其页码数oage默认值是1,展示第一页的canvas。所以我们主要使用两种方式处理。
第一种是使用v-for循环加载所有页面:
<template>
<pdf src=""></pdf>
</template>
<script>
import pdf from 'vue-pdf'
exprot default {
component: {
pdf
}
}
</script>
这个时候,多页的PDF只会显示第一页,这时各位可以去查看一下vue-pdf的源码,我们可以发现,它的实现过程是将PDF按页绘制在canvas上的,其页码数oage默认值是1,展示第一页的canvas。所以我们主要使用两种方式处理。
第一种是使用v-for循环加载所有页面:
<template>
<div>
<pdf
v-for="i in numPages"
:key="i"
:src="src"
:page="i"
style="display: inline-block; width: 25%"
></pdf>
</div>
</template>
<script>
import pdf from 'vue-pdf'
var loadingTask = pdf.createLoadingTask('https://cdn.mozilla.net/pdfjs/tracemonkey.pdf');
export default {
components: {
pdf
},
data() {
return {
src: loadingTask,
numPages: undefined,
}
},
mounted() {
this.src.promise.then(pdf => {
this.numPages = pdf.numPages;
});
}
}
</script>
这样有一个问题就是如果页数非常多,加载会很慢。
第二张是采用分页的形式:
<template>
<div class="onlineHelp cg-box">
<div class="tools">
<div class="page">第 {{pageNum}} /{{pageTotalNum}}页 </div>
<el-input v-model.number="goPageNum" style="width: 70px;margin-right: 8px"></el-input>
<el-button type="success" @click.stop="goPage"> 前往</el-button>
<el-button type="primary" @click.stop="prePage"> 上一页</el-button>
<el-button type="primary" @click.stop="nextPage"> 下一页</el-button>
</div>
<div class="pdf-box">
<pdf ref="pdf"
:src="url"
:page="pageNum"
@progress="loadedRatio = $event"
@page-loaded="pageLoaded($event)"
@num-pages="pageTotalNum=$event"
@error="pdfError($event)"
@link-clicked="page = $event">
</pdf>
</div>
</div>
</template>
<script>
import pdf from 'vue-pdf'
export default {
name: 'onlineHelp',
components: {
pdf
},
data() {
return {
url: `${process.env.VUE_APP_BASEURL}/help.pdf`,
pageNum: 1,
pageTotalNum: 1,
// 加载进度
loadedRatio: 0,
curPageNum: 0,
goPageNum: 1
};
},
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
},
// 前往页数
goPage() {
if(!this.goPageNum || /\D/.test(this.goPageNum) || this.goPageNum < 1 || this.goPageNum > this.pageTotalNum) {
this.$message.warning('输入页码有误')
return
}
this.pageNum = this.goPageNum
},
// 页面加载回调函数,其中e为当前页数
pageLoaded(e) {
this.curPageNum = e
},
// 其他的一些回调函数。
pdfError(error) {
console.error(error)
}
}
};
</script>
<style lang="scss">
.onlineHelp {
height: 100%;
position: relative;
display: flex;
justify-content: center;
.tools {
position: absolute;
top: 10px;
right: 10px;
z-index: 999;
.page {
display: inline-block;
margin-right: 10px;
}
}
.pdf-box {
height: 100%;
overflow: auto;
width: 90%;
}
}
</style>
二、
<template>
<div class="wrap">
<pdf v-for="item in numPages" :key="item" :src="pdfSrc" :page="item"/>
</div>
</template>
<script>
import pdf from 'vue-pdf'
import CMapReaderFactory from 'vue-pdf/src/CMapReaderFactory.js'
export default {
components:{
pdf
},
data(){
return{
pdfUrl: "http://192.168.0.223:8080/pdf/预报.pdf",
pdfSrc: "",
numPages: "",
}
},
mounted(){
this.getTitlePdfurl();
},
methods:{
getTitlePdfurl(){
this.pdfSrc = pdf.createLoadingTask({ url: this.pdfUrl, CMapReaderFactory });//解决中文乱码问题
this.pdfSrc.promise.then((pdf) => {
this.numPages = pdf.numPages;
})
},
}
}
</script>
<style lang="less" scoped>
.wrap{
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
</style>