vue前端预览pdf并加水印、ofd文件,控制打印、下载、另存,vue-pdf的使用方法以及在开发中所踩过的坑合集

这篇具有很好参考价值的文章主要介绍了vue前端预览pdf并加水印、ofd文件,控制打印、下载、另存,vue-pdf的使用方法以及在开发中所踩过的坑合集。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

根据公司的实际项目需求,要求实现对pdf和ofd文件的预览,并且需要限制用户是否可以下载、打印、另存pdf、ofd文件,如果该用户可以打印、下载需要控制每个用户的下载次数以及可打印的次数。正常的预览pdf很简单,直接调用浏览器的预览就可以而且功能也比较全,但是一涉及到禁止用户打印、另存的话就不可以用浏览器自带的预览方式了。那就只能寻找插件来模拟了,之前在eletron-vue项目中使用过pdfjs以及vue-pdf插件,效果不是特别好,vue-pdf底层其实也是用的pdfjs的东西,当时在客户端项目中莫名的报一些错误(可能是因为版本问题,当时项目比较着急没有太多时间去排坑)果断弃坑选择了iframe预览pdf文件,也可以达到当时项目需求。但是,目前的需求背景是管理端以及门户端想要实现此功能,脱离了electron的限制,我决定还是使用vue-pdf比较靠谱,我也简单安装并测试使用了一下,没有问题可以正常预览本地文件并且并没有报electron中的不知名的错误。下面先来说一下插件的具体使用方法:

1.安装vue-pdf依赖:

npm/yarn i/add vue-pdf

2.import导入并注册依赖(哪个界面需要在哪个界面单独导入即可)

// 单组件引用
import pdf from 'vue-pdf' 
// 然后在component中进行注册
components: {
  pdf
},

3.界面中使用vue-pdf

// 点击分页
<div>
  <el-button size="small" type="primary"  @click="changePdfPage(0)" class="turn" :class="{grey: currentPage==1}">上一页</el-button>
  {{currentPage}} / {{pageCount}}
  <el-button size="small" type="primary"  @click="changePdfPage(1)" class="turn" :class="{grey: currentPage==pageCount}">下一页</el-button>
</div>
<div class="content" ref="printContent">
  <pdf
    id="myIframe"
    ref="pdfDom"
    :src="pdfSrc" 
    :page="currentPage" 
    @num-pages="pageCount=$event" 
    @page-loaded="currentPage=$event" 
    @loaded="loadPdfHandler"> 
  </pdf>
</div>
// 声明变量
data() {
  return {
    pdfSrc: '', // pdf文件src
    pageCount: 0, // pdf文件总页数
    currentPage: 1, // pdf文件页码
  }
},
// 获取文件流和文件总页数 
async getFileInfo() {
  let formData = new FormData();
  formData.append('wjid', this.wjid)
  formData.append('yhid', this.userId)
  let res = await getFileBuffer(formData)
  if(res.status === 200){
    const blob = new Blob([res.data])
    let pageRes = await getFilePages(formData)
    this.pdfSrc = URL.createObjectURL(blob)
    this.pageCount = pageRes.data.content
  }else{
  	this.$message({
  		message: res.message,
  		type: 'error'
  	});
  }
},
// 改变PDF页码,val传过来区分上一页下一页的值,0上一页,1下一页
changePdfPage (val) {
  if (val === 0 && this.currentPage > 1) {
    this.currentPage--
  }
  if (val === 1 && this.currentPage < this.pageCount) {
    this.currentPage++
  }
},

// pdf加载时
loadPdfHandler (e) {
  this.currentPage = 1 // 加载的时候先加载第一页
},

以上代码是从后端获取pdf文件的文件流,await getFileBuffer(formData)请求接口赋值给res,根据res的状态值为200进行判断文件流是否成功返回,返回成功后通过new Blob([res.data]) 转换成blob,然后通过URL.createObjectURL(blob)获取pdfSrc。

await getFilePages(formData)接口是单独获取pdf总页数。

vue-pdf,vue.js,前端,pdf

上图为根据后端返回的pdf数据流预览的此pdf文件,现在只是把pdf文件显示出来了,目前仅仅成功了一小部分,可以说刚刚把这部分功能最基础的部分弄完,后续还会有控制打印、下载、另存、水印…

我们可以一个一个来实现,首先说一下禁止浏览器的快捷键ctrl+s(保存)、ctrl+p(打印),可以通过以下代码禁止当前界面这两个快捷键的使用,直接上代码:
mounted() {
  // 禁止ctrl+S保存   禁止ctrl+P打印
  document.addEventListener(
    "keydown",
    function (event) {
      // 禁止ctrl+s
      if (event.ctrlKey === true && event.which === 83) {
        // console.log('ctrl+s');
        event.preventDefault();
      }else if(event.ctrlKey === true && event.which === 80) {
      // 禁止ctrl+p
        event.preventDefault();
      }
    },
    false
  );  
}
文件下载,界面上写好下载按钮,写好click点击事件以及v-if(控制此用户的下载次数,根据用户每次点击下载按钮后台计算下载次数,如果下载次数达到设置的次数,隐藏下载按钮)直接上代码:
<el-button size="small" class="cz-button" type="primary" v-if="downLoadShow" @click="downloadClick">下载文件</el-button>


// 下载方法
async downloadClick() {
    this.fileName = '' // 获取文件名
    let formData = new FormData();
    formData.append('wjid', this.wjid)
    formData.append('yhid', yhid)
    let res = await getFileBufferDl(formData)
    // 根据用户id和文件id向后台请求接口返回pdf文件流
    const blob = new Blob([res])
    const url = window.URL.createObjectURL(blob) 
    let dom = document.createElement('a')
    dom.style.display = 'none'
    dom.href = url
    dom.setAttribute('download', this.fileName)
    document.body.appendChild(dom)
    // 执行下载操作
    dom.click()
    // 下载完成以后向后台发起接口 传入用户id 后台将该用户的下载次数进行加1
    ......	
},
文件打印,界面上写好下载按钮,写好click点击事件以及v-if(控制此用户的打印次数,根据用户每次点击打印按钮后台计算打印次数,如果打印次数达到设置的次数,隐藏打印按钮)打印需要下载print-js依赖

1.安装依赖

yarn add print-js

2.引入插件

import printJS from 'print-js'

3.使用插件(直接传入文件的路径)

printJS(url)

4.官方文档https://printjs.crabbly.com/

<el-button size="small" style="margin-right: 90px;" class="cz-button" type="primary" v-if="printShow" @click="billPrintClick">打印</el-button>

// 打印方法
billPrintClick() {
    this.$nextTick(async () => {
        let formData = new FormData();
        formData.append('wjid', this.wjid)
        formData.append('yhid', yhid)
        let res = await getFileBufferDl(formData)
        const blob = new Blob([res])
        const url = window.URL.createObjectURL(blob) //URL.createObjectURL(object)表示生成一个File对象或Blob对象
        printJS(url)
        let resName = await getProfile()
        // 下载完成以后向后台发起接口 传入用户id 后台将该用户的下载次数进行加1
        ......
    })
},
文件预览水印,正常加水印流程是java后端把文件加上水印后返回给前端,前端可以直接预览、下载、打印带有水印的文件,之前弄过前端加水印方法也比较简单,从网上找了个前端加水印的例子,简单调整了一下,在这也做下记录:
<div class="content" id="myIframe" ref="printContent">
  <pdf ref="pdfDom" :src="pdfSrc" :page="currentPage" @num-pages="pageCount = $event" @page-loaded="currentPage = $event" @loaded="loadPdfHandler"></pdf>
</div>
// 调用方法传入的参数是水印内容根据实际需求而定,我这里写的是获取当前用户的中文用户名直接传入方法里即可
this.$nextTick(async () => {
  this.setWatermarkContent(resName.data.userInfo.userName);
  window.onresize = () => {
    this.setWatermarkContent(resName.data.userInfo.userName);
  };
});

// 设置水印
setWatermarkContent(resName) {
			// 创建canvas容器
			let ele = document.createElement("canvas");
			ele.width = 250;
			ele.height = 200;
            // 水印参数对象
			let objmsg = {
				canvas: ele,
				fontText: resName, // 显示的内容,显示方法传入的内容 字符串格式
				fontSize: 20, // 水印的字体大小
				fontFamily: "microsoft yahei", // 字体 
				fontcolor: "#dadbdc", //字体颜色   默认 #dadbdc
				rotate: 25, //旋转角度   数字类型
				textAlign: "left", //水印文字居中方式:left center right  默认 left
			};
			this.createWaterMark(objmsg);
			this.drawWaterMark(ele); // 将水印canvas遮罩层定位到pdf容器中
		},
		// 创建canvas水印图片
		createWaterMark({ canvas, fontText, fontFamily = "microsoft yahei", fontSize = 30, fontcolor = "#dadbdc", rotate = 30, textAlign = "left" }) {
			let ctx = canvas.getContext("2d");
			ctx.font = `${fontSize}px ${fontFamily}`;
			ctx.rotate((-rotate * Math.PI) / 180);
			ctx.fillStyle = fontcolor;
			ctx.textAlign = textAlign;
			ctx.textBaseline = "Middle";
			ctx.fillText(fontText, canvas.width / 6, canvas.height / 2);
		},
		// 给pdf增加水印遮罩层
		drawWaterMark(ele) {
			let div = document.createElement("div");
			div.style.pointerEvents = "none";
			div.style.position = "absolute";
			div.style.background = "url(" + ele.toDataURL("image/png") + ") left top repeat";
            // 获取容器的宽度和高度
			let width = document.getElementById("myIframe").clientWidth || 700;
			let height = document.getElementById("myIframe").clientHeight || 700;
			div.style.width = width + "px";
			div.style.height = height + "px";
			document.getElementById("myIframe").appendChild(div);
		}

上面主要是介绍vue-pdf、printjs插件以及怎么前端控制下载、另存以及打印功能,那么接下来重点说一下vue-pdf这个插件,总结一下我在开发过程中所遇到过的坑,仅供参考可能解决方法有很多种

分割线分割线,这是一条分割线—分割线分割线,这是一条分割线—分割线分割线,这是一条分割线—分割线分割线,这是一条分割线

1. 本地开发时预览一点毛病都没有,就是build打完包后放到服务器上无法预览报错:提示xxx.worker.js 500 或者 404
解决方法:需要改两个地方:
① 修改依赖下的文件位置:node_modules/vue-pdf/src/vuePdfNoSss.vue

vue-pdf,vue.js,前端,pdf
vue-pdf,vue.js,前端,pdf
注意:代码中需要注释的那一行有的版本路径不一样
有的是:// var PdfjsWorker = require('worker-loader!pdfjs-dist/build/pdf.worker.js');
有的是:// var PdfjsWorker = require('worker-loader!pdfjs-dist/es5/build/pdf.worker.js');

② 找到项目的vue.config.js 文件,在配置文件中新家下面这段代码
    // 处理vue-pdf打包文件404
    config.module
    .rule('worker')
    .test(/\.worker\.js$/)
    .use('worker-loader').loader('worker-loader')
    .options({
        inline: true,
        fallback: false,
    }).end();
两个地方改完之后再执行yarn run build打包部署到服务器上发现不会报xxx.worker.js 500 或者 404这种错了,可以正常预览了!

vue-pdf,vue.js,前端,pdf

2. 线上环境大部分pdf预览都没有问题,但是有个别pdf文件里面的内容显示不全,缺胳膊少腿,不是这个字没显示出来就是那个字丢了的(本地还是没有问题)
解决方法:在网上找了一下,也有人遇到类似问题,原因是缺少相应字体 ,需要在界面上引入CMapReaderFactory,然后把url传进去生成新的路径赋值给this.pdfSrc,就可以解决
import pdf from 'vue-pdf'
import CMapReaderFactory from 'vue-pdf/src/CMapReaderFactory'

let loadingTask = pdf.createLoadingTask({
  url: URL.createObjectURL(blob),
  cMapPacked: true,
  CMapReaderFactory
})
this.pdfSrc = loadingTask;
3. 当我们使用上个问题中的CMapReaderFactory时,会引发另外一个问题,就是预览的时候显示空白的问题,显示不全有空白页,控制台还不报错
我也去网上找了相关问题的解决方法,有人说是因为缓存问题,第二次加载时取的是初次加载PDF文件时的语言文件的loadModules的缓存,但是取的过程中导致了失败,返回了空值,修改的时候只需要加上一段话
//加载完语言文件后清除缓存
delete require.cache[require.resolve('./buffer-loader!pdfjs-dist-sign/cmaps/'+query.name+'.bcmap')];

vue-pdf,vue.js,前端,pdf文章来源地址https://www.toymoban.com/news/detail-567203.html

4. 打包部署到服务器上后,预览时死活看不到内容,控制器不报错,就是空白,本地开发也没问题
这个问题啥招我都试了,我同时做管理端以及门户端,都需要预览pdf,用的都是vue-pdf,代码逻辑一模一样,而且后台接口也一模一样,门户端开发环境和部署环境一点问题都没有,管理端开发环境没问题部署完以后到线上就是不展示内容,这个问题我改了一天,没办法在本地测试,只能改一点发给现场一个包现场部署一版给我测一下好不好用,一天我给现场发包就发了20个,马上下班的时候我给现场发了个包,和现场哥们说这个不行就暂时换回备份的包吧,说实话我对这个包真没报啥希望。竟然解决了,我听到以后都震惊了改了一天给现场发了20个包,最后这个包啥都没改竟然好用了,我也很诧异,最后发现是我把vue-pdf降了几个版本,什么都没改就好使了。之前用的是最新的"vue-pdf": “4.3.0”,我卸了重新按了个4.0.7的竟然解决了!!!
5. Uncaught SyntaxError: Unexpected token ‘<‘
从接触vue-pdf开始,就感觉不是啥善茬,最开始是在electron-vue项目中接触,安装完依赖以后就报Uncaught SyntaxError: Unexpected token ‘<‘这个错,网上找了好多这个问题的解决方法,但是并没有什么用,最后这个问题也没解决,在electron项目中直接弃坑了,换成iframe预览pdf文件,也可以达成想要的效果。

到了这里,关于vue前端预览pdf并加水印、ofd文件,控制打印、下载、另存,vue-pdf的使用方法以及在开发中所踩过的坑合集的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Vue3前端h5移动端页面预览PDF使用pdfjs-dist,添加自定义文本水印

    pnpm i pdfjs-dist@2.5.207

    2024年01月18日
    浏览(77)
  • 前端小程序,h5,浏览器,app, doc,.docx,.ofd,.PDF,.WPS以及Office文档的在线解析预览方式

    在线预览是将Word、PPT、Excel、PDF、OFD、音视频等文件在浏览器中解析查看。       我使用的是usdoc,也有用office online进行在线预览,不过注意的是使用usdoc的时候,我们先需要注册和添加预览的地址域名 usdoc的地址:http://www.usdoc.cn 进入用户中心,我们进行注册 注册好之后,先

    2024年02月11日
    浏览(64)
  • 【vue2】纯前端实现本地的pdf/word/epub文件预览

    需求是预览本地的pdf/word/epub格式的文件,但是搜索后发现没有可以直接使用的,格式不同,显示的方式和效果也都略有不同。 最后还是 分别实现预览 的功能。 如果只需要预览pdf/word等格式的话,可以使用的方案:vue-office,支持多种文件(docx、excel、pdf)预览的vue组件库,支持

    2024年02月11日
    浏览(76)
  • 前端(vue)js在线预览PDF、Word、Excel、ppt等office文件

    可选参数 pdf=true,word文档尝试以pdf方式显示,默认false watermark=水印文本,显示文本水印;“img:”+图片url表示图片水印,如:img:https://view.xdocin.com/demo/wm.png saveable=true,是否允许保存源文件,默认false printable=false,是否允许打印,默认true ©able=false,是否允许选择复制内容,

    2024年02月13日
    浏览(77)
  • vue 项目中实现pdf预览 pdf打印 pdf下载

    在Vue项目中实现PDF预览、打印和下载可以通过以下步骤来实现: 安装pdf.js pdf.js是一个JavaScript库,可以用于在Web上渲染PDF文件。 可以使用npm安装pdf.js,命令如下: npm install pdfjs-dist --save 创建一个PDF组件 在Vue项目中,可以创建一个PDF组件,用于显示PDF文件。 可以使用pdf.js提供

    2024年02月13日
    浏览(73)
  • 【vue2】纯前端实现本地的pdf/word/epub文件预览(包括pdf选中文字,epub高亮等)

    需求是预览本地的pdf/word/epub格式的文件,但是搜索后发现没有可以直接使用的,格式不同,显示的方式和效果也都略有不同。 最后还是 分别实现预览 的功能。 如果只需要预览pdf/word等格式的话,可以使用的方案:vue-office,支持多种文件(docx、excel、pdf)预览的vue组件库,支持

    2024年02月11日
    浏览(61)
  • vue3管理系统中后台返回pdf格式的文件流,前端如何预览?以及uniapp微信小程序中后台返回的base64位的pdf文件如何预览?

    后台返回的是base64格式的pdf文件,首先需要解析base64文件的插件 image-tools 1 安装并引入插件 2 封装预览pdf的函数 3 调用接口获取数据

    2024年01月18日
    浏览(92)
  • Vue3预览并打印PDF的两种方法

    项目场景:后台接口请求数据,返回PDF文档的链接(即pdf文件在服务器上的存放路径),在vue3页面可预览和打印该PDF。 在之前的Vue2项目中,预览并打印PDF用的是vue-pdf这个插件,但在vue3中是不支持的,只能换个插件了,于是经过测试,也踩了一些坑,总结了以下两种方法:

    2023年04月18日
    浏览(43)
  • 前端vue3实现本地及在线文件预览(含pdf/txt/mp3/mp4/docx/xlsx/pptx)

    (一)微软office免费预览( 推荐 ) 支持doc/docx/xls/xlsx/ppt/pptx等多种office文件格式的免费预览 (二)XDOC文档预览云服务  移动端和PC端无插件预览PDF、OFD、Word、WPS等多种格式文档 本地或内网预览需要借助插件实现,pdf、mp3、mp4等主要靠原生标签或浏览器自带功能,尽量减少

    2024年02月05日
    浏览(74)
  • 前端实现PDF预览【vue】

    前言:项目中提出这样一个需求,在移动端H5页面预览pdf功能。pdf文件由后端返回的一个地址,前端实现展示预览pdf文件 在此仅提供两种方法: 一、使用iframe标签通过src属性直接展示pdf文件         坑点:兼容比较差,PC端能正常展示,移动端会出现空白的问题 二、使用第

    2024年01月16日
    浏览(54)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包