PDF 预览与下载
功能描述:
- 在项目中点击PDF文件然后跳转到一个对话框,展示PDF的内容,然后还有分页和下载的功能。
使用的框架和具体的插件:
vue@2.5.16
,vue-pdf-signature
使用方法:
-
描述:
在父组件中调用封装好的组件
pdf
(实现预览PDF的功能),然后当点击PDF时给子组件一个后端返回的PDF的地址,就可以实现效果。 -
问题:
因为vue-pdf出现的各种问题,这里使用vue-pdf-signature,替换vue-pdf。字体有时候会出现缺失的情况,所以需要找到下面路径(
node_modules/vue-pdf/build/pdf-dist/cmaps
)下的文件夹复制然后放到static下面。然后再组件里面直接引用,这样在解析的时候就不会出现字体丢失了。cmaps
-
代码如下:
PdfPriview页面的代码
<template>
<div class="pdfPreview">
<el-dialog
:close-on-click-modal="false"
:visible.sync="dialogVisible"
:fullscreen="true"
:before-close="handleClose"
title="合同预览">
<div class="agreement_picture">
<div class="tools">
<el-button @click="prePage" class="mr10"> 上一页</el-button>
<el-button @click="nextPage" class="mr10"> 下一页</el-button>
<span class="page">{{pageNum}}/{{pageTotalNum}} </span>
<el-button @click="handleClose" class="mr10 fl-r btn-cancel"> 取消</el-button>
<el-button @click="downPDF" class="mr10 dowmBtn"> 下载</el-button>
</div>
<pdf ref="pdf"
:src="src"
:page="pageNum"
@page-loaded="pageLoaded($event)"
@num-pages="pageTotalNum=$event"
@error="pdfError($event)"
@link-clicked="page = $event">
</pdf>
</div>
</el-dialog>
</div>
</template>
<script>
import pdf from 'vue-pdf-signature';
export default {
name: 'PdfPreview',
components: {
pdf
},
props:{
dialog: {
type: Boolean,
default: false
},
urlPdf:{
type:String,
default:''
}
},
data() {
return {
dialogVisible:this.dialog,
url:this.urlPdf,
src: '', // 预览地址
pageNum: 1, // 当前页码
pageTotalNum: 1, // 总页数
};
},
mounted () {
// 有时PDF文件地址会出现跨域的情况,这里最好处理一下
var url = this.url
this.src = pdf.createLoadingTask({
url,
cMapUrl: '../../../../static/cmaps/',
cMapPacked: true,
});
},
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
},
// 页面加载回调函数,其中e为当前页数
pageLoaded(e) {
this.curPageNum = e
},
// 抛出错误的回调函数。
pdfError(error) {
console.error(error)
},
downPDF() { // 下载 pdf
var url = this.url
var tempLink = document.createElement("a");
tempLink.style.display = "none";
tempLink.href = url;
tempLink.setAttribute("download", 'XXX.pdf');
if (typeof tempLink.download === "undefined") {
tempLink.setAttribute("target", "_blank");
}
document.body.appendChild(tempLink);
tempLink.click();
document.body.removeChild(tempLink);
this.handleClose();
},
handleClose() {
// this.$emit('update:dialogVisible', false);
// this.$emit('updata:url','');
this.$emit('update',false);
}
}
};
</script>
<style scoped>
.wrap{
position: fixed;
top: 0;
left: 0;
width: 100%;
bottom: 0;
}
</style>
父组件的代码
<template>
<div>
<el-dialog :title="dialogTitle" :visible.sync="editDialog" width="770px"
:close-on-click-modal="false" :close-on-press-escape="false" @close="dialogClose">
<div class="dialog-div">
<el-form label-width="110px">
<div class="inline-div">
<el-form-item label="企业名称:">
<div class="handle-input">{{detailForm.companyName}}</div>
</el-form-item>
<el-form-item label="位置:">
<div class="handle-input">{{detailForm.location}}</div>
</el-form-item>
</div>
<div class="inline-div">
<el-form-item label="联系人:">
<div class="handle-input">{{detailForm.contact}}</div>
</el-form-item>
<el-form-item label="联系方式:">
<div class="handle-input">{{detailForm.contactInformation}}</div>
</el-form-item>
</div>
<el-form-item label="备注:">
<div class="handle-row-input">{{detailForm.remark}}</div>
</el-form-item>
<el-form-item label="附件:">
<div style="display: flex;flex-direction: column;">
<el-upload ref="uploadImg"
action=""
:disabled="true"
accept=".pdf,.jpg,.jpeg,.png,.PNG,.bmp,.JPG,.JPEG"
:on-preview="handlePreview"
:file-list="fileList">
</el-upload>
</div>
</el-form-item>
</el-form>
</div>
<!-- <div class="btn-div">-->
<!-- <el-button type="primary" @click="cancleSubmit">关闭</el-button>-->
<!-- </div>-->
</el-dialog>
<pdf-preview :dialog='pdfBoo' :urlPdf='pdfUrl' v-if="pdfBoo" @update="closeUpdate"></pdf-preview>
</div>
</template>
<script>
export default {
data(){
return {
pdfBoo:false,
pdfUrl:''
}
},
methods: {
closeUpdate(val){
this.pdfBoo = val;
},
handlePreview(file) {
if (file.name.endsWith(".pdf")) {
this.pdfBoo= true;
this.pdfUrl = file.response.data;
} else {
this.dialogImageUrl = file.response.data;
this.dialogVisible = true;
}
},
}
</script>
遇到的问题:
- 主要在父组件一加载就会报错,然后解决一直出问题,最后在父组件中给子组件加上判断
v-if
当需要的时候给她true
让在在渲染,问题解决。