vue使用pdf.js实现在线查看pdf文件

需求:有一个列表页,用户点击查看,弹层展示后台接口返回的pdf内容(不是文件、地址之类的,乱码的pdf铭文(二进制文件流))

1、pdf.js安装

复制代码
npm install --save vue-pdf

2、正文代码

复制代码
<template>
    <div>
		<el-table :data="dataList">
	        <el-table-column prop="fieldName" width="120" label="操作">
	          <template slot-scope="scope">
	            <span @click="look(scope.row)">查看</span>
	          </template>
	        </el-table-column>
       </el-table>
	   <el-dialog title="预览" :visible.sync="dialogVisible" :before-close="closePdf">
      	 <pdf v-for="i in numPages" :key="i" :src="pdfSrc" :page="i" />
       </el-dialog>
	</div>
<template>
<script>
	import pdf from 'vue-pdf'
	export default {
	  components: {
	    pdf
	  },
	  data() {
   		 return {
  		 	  dialogVisible: false,
		      numPages: 1,
		      pdfSrc:"",
		      close:false,
   		 }
   	  },
   	  methods: {
		// 查看预览
	    look(row) {
	      const that = this;
	      that.pdfSrc = "";
		  // 接口文件地址(接口入参拼出来的路径)
	      const url = `${Host}xxxxxx/xxxx/xxx?fileId=${row.fileId}&amp;fileName=${row.fileName}.pdf`;
		  // 如果调用接口(接口的responseType一定要是blob,默认json,不然解析出来的pdf是空白的)后拿的返回的值(乱码的pdf铭文(二进制文件流))则需要转一下
		  // const url = window.URL.createObjectURL(new Blob([res]), { // res为接口返回值
			// type: "application/msword"
		  // });
	      that.pdfSrc = pdf.createLoadingTask(url)
	      that.pdfSrc.promise.then(pdf => {
	        that.dialogVisible = true;
	        that.numPages = pdf.numPages
	        //保证pdf加载成功,否则不能关闭弹层
	        setTimeout(() => {
	          that.close = true;
	        }, 2000);
	      })
	      .catch(error => {
	        that.$message.error("无效的PDF文件!");
	      })
	    },
	    //此方法解决第一次查看pdf文字没有加载完成影响后续查看
	    closePdf(done){
	      if(this.close) {
	        this.numPages = 1;//必须重置,多次查看会出现头部内容缺失
	        this.close = false;
	        done();
	      } else {
	        this.$message.warning("PDF文件加载中");
	      }
	    }
	  }
	}
</script>

遇到的问题:

1、多次查看后头部内容不显示。 设置numPages = 1;

2、上一条pdf查看没有加载完成,下一条pdf查看pdfSrc清空了还是无法正常加载。 延迟关闭弹层(这个方法有点暴力,希望能找到好的解决方法);

3、头部会有点多余内容溢出,内容没啥,就是感觉有类似border的东西。 头部其他内容设置样式盖住(具体css略)。

在后续项目中又实现了该功能,没有遇到以上问题,盲猜是因为pdf dialog标签上加了v-if,光设置visible.sync只会控制元素的显示隐藏,不会重新渲染。

总结:只要是dialog最好加上v-if,会避免很多问题。

拓展:

如果后端返回的是html格式,前端调用的接口responseType就不要用blob了,直接将返回结果放在v-html里面。例:

复制代码
<div v-html="responseData"/>
相关推荐
夏幻灵6 小时前
JavaScript this 面试:五种绑定规则、优先级与常见面试陷阱
开发语言·javascript·面试
三天不学习6 小时前
Egg.js 4 突然爆火,原因是否归结于AI 原生落地需求爆发?
前端·javascript·全栈·egg.js
xcs194057 小时前
前端 vue 的前端页面debugger 进不去
前端·javascript·vue.js
雪芽蓝域zzs10 小时前
第 5 节:Marker 点击弹出 InfoWindow 信息窗口
vue.js
小宋102112 小时前
A2UI从零实战:Agent安全生成交互界面与事件回传
javascript·人工智能·安全·交互
大包子13 小时前
structuredClone vs lodash.cloneDeep:核心差异与选型指南
javascript·vue.js
lerhxx13 小时前
AI 应用中的上下文管理 —— 从"上下文窗口"到"分层压缩"的工程实践
前端·javascript
雪芽蓝域zzs13 小时前
第 3 节:地图点击事件,点击获取经纬度
vue.js
Mahut14 小时前
我在 Mac 上做了个本地剪辑器
javascript·架构·产品
WayneX14 小时前
开源 Vue 3 组件库 Morya UI:把组件、文档、AI 工具链一起做进一个包
前端·vue.js·前端框架