vue实现不预览PDF的情况下打印pdf文件

前景:默认情况,实现打印需要根据预览的内容进行打印。
但是当只有打印按钮存在,不预览文件内容的情况下,实现打印的话,可以通过后端接口返回服务器上PDF的地址,前端通过隐藏的iframe标签中src可实现预览功能
主要是根据pdf的链接地址实现打印pdf

实现方式1:通过fetch()将PDF地址转化为blob

	print(row) {
      let contractUrl = "http://xxxxxx.pdf"
      fetch(contractUrl).then(res => {
        return res.blob() //将url地址转化为blob
      }).then(res => {
        var iframe = document.createElement('iframe')
        iframe.style.frameborder = 'no'
        iframe.style.display = 'none'
        iframe.style.pageBreakBefore = 'always'
        iframe.setAttribute('id', `printPdf${row.pk}`) //id要是唯一的,不然会获取到上一个PDF文件的内容
        iframe.setAttribute('name', `printPdf${row.pk}`)
        iframe.src = window.URL.createObjectURL(res) //创建一个包含指定对象的URL
        document.body.appendChild(iframe)
        this.doPrint(`printPdf${row.pk}`)
        window.URL.revokeObjectURL(iframe.src) //释放url
      })
    },
    doPrint(val) {
      var ordonnance = document.getElementById(val).contentWindow
      setTimeout(() => {
        ordonnance.print()
      }, 500)
    },

后端返回的数据是文档流的情况下
在这里插入图片描述

实现方式2:采用文档流的形式解决跨域的问题【不使用】

缺陷:在没有文件页面的情况下,这种打开打印窗口的方式会存在文件缓存的问题,就是在pdf文件内容修改后,打印窗口不是最新的文件内容。

print() {
	// res为接口获取到的pdf文档流数据
	const blob = new Blob([res], {
		type: 'application/pdf'
	})
	var iframe = document.createElement('iframe')
	iframe.style.frameborder = 'no'
	iframe.style.display = 'none'
	iframe.style.pageBreakBefore = 'always'
	iframe.setAttribute('id', 'printPdf')
	iframe.setAttribute('name', 'printPdf')
	iframe.src = window.URL.createObjectURL(blob) //创建一个包含指定对象的URL
	document.body.appendChild(iframe)
	this.doPrint('printPdf')
	window.URL.revokeObjectURL(iframe.src) //释放url

},
doPrint(val) {
	var ordonnance = document.getElementById(val).contentWindow
	setTimeout(() => {
		ordonnance.print()
	}, 500)
},

实现方式2补充:接口返回pdf文档流进行打印实现方式【可使用】

这种方式可以保证打印窗口每次预览的文件都是最新的

async print() {
	// res为接口获取到的pdf文档流数据
    const blob = new Blob([res], {
      type: 'application/pdf'
    })
    let iframe = document.createElement("iframe");
    iframe.style.display = "none";
    iframe.src = window.URL.createObjectURL(blob); //创建一个包含指定对象的URL
    document.body.appendChild(iframe);
    // 打开打印对话框
    iframe.contentWindow.focus();
    iframe.contentWindow.print();
    window.URL.revokeObjectURL(iframe.src); //释放url
  },

实现方式3:打印pdf并且可以调整样式(比如边距)

点击打印按钮,直接打印pdf文档的情况下,会存在不同浏览器的文档打印出来的边框距离不一样的情况。

在浏览器上执行打印PDF文件时,不能调整边距,而选择打印图片格式的文件时可以调整边距。所以可以尝试把文件格式改为图片格式来直接打印。

使用window.print()打印的时候,@media print只能改web网页上的内容,比如canvas,html标签等

实现流程:利用pdfjs-distpdf文件流转换成canvas,然后将canvas转成imgsrc地址格式,再利用print-js直接打印图片,并且修改样式

使用的安装包版本

"pdfjs-dist": "2.6.347",
"print-js": "^1.6.0",

实现方法

<button @click="loadPdfData">打印</button>
<script>
import api from "@/api"; // 修改成自己的接口api
import printJS from "print-js";
export default {
  data() {
    return {
    };
  },
  methods: {
  	// 获取pdf的文档流数据
    getPdfUrl() {
      return api.getPdfFile(; // 修改成自己的接口api
    },
    async loadPdfData() {
      const res = await this.getPdfUrl(); // res是pdf文档流
      // 拿到文档流数据
      const blob = new Blob([res.data], {
        type: "application/pdf",
      });
      let url = window.URL.createObjectURL(blob);
      const pdfjs = await import("pdfjs-dist/build/pdf.js");
      const pdfjsWorker = await import("pdfjs-dist/build/pdf.worker.entry");
      pdfjs.GlobalWorkerOptions.workerSrc = pdfjsWorker;

      //读取pdf流文件 加载PDF文档
      const loadingTask = pdfjs.getDocument(url);
      const pdf = await loadingTask.promise;
      const numPages = pdf.numPages;
      const canvasList = [];

      // 遍历每一页并将其渲染到 canvas 上,转成图片
      for (let pageNumber = 1; pageNumber <= numPages; pageNumber++) {
        // 获取pdf页
        const page = await pdf.getPage(pageNumber);
        // 设置缩放比例,可根据需要调整
        const scale = 6;
        // 获取页的尺寸
        const viewport = page.getViewport({ scale });

        // 创建 canvas 元素
        const canvas = document.createElement('canvas');
        const context = canvas.getContext('2d');
        // 设置canvas的尺寸
        canvas.height = viewport.height;
        canvas.width = viewport.width;

        // 将pdf页渲染到canvas上
        const renderContext = {
          canvasContext: context,
          viewport: viewport
        };
        await page.render(renderContext).promise;

        canvasList.push(canvas);
      }

      // 将 canvas 转换为图片的 DataURL 数组
      const imageUrls = canvasList.map(canvas => canvas.toDataURL('image/png'));
      
      if (!imageUrls.length) {
        this.$conforms({
          title: "提示",
          content: "文件获取失败,请重新打印!",
          rightBtnText: "关闭",
          rightBtn: () => {},
        });
        return;
      }

      // 使用 print-js 打印图片
      printJS({
        printable: imageUrls,
        type: 'image',
        style:
          "@media print{ @page { size: A4; margin: 20px; mso-header: none; mso-footer: none; } body{margin: 0px}}",
      }); // 修改打印窗口的边距样式等
    },
  },
};
</script>
 // 解释:scale可以设置图片的清晰度问题,值越大越清晰,但是图片也会越大
 const viewport = page.getViewport({ scale: 6 });

说明:
使用的@page是一种 CSS 规则,用于修改打印页面的不同方面。它的目标是修改页面的尺寸、方向和页边距。
@page {size: A4;margin: 0; mso-header:none: none; ;mso-footer·: none;}
size: 打印纸大小
margin:打印区域外边距
mso-header:设置页头
mso-footer:设置页脚
body{margin:0px} 图片外边距,设置上下均为0 可以去掉空白的首页和尾页

注意:打印窗口的设置不同,会导致出现不一样的内容, 比如linux系统和windows系统,预览出来的pdf可能会出现字体不一致。比如勾选了页眉和页脚,右下角会出现多余的符号/

实现方式4

后端接口直接返回图片文件流,利用print-js进行打印

   // res为服务端返回的数据流,图片格式
   let data = new Blob([res]);
   let file = new Blob([data]);
   let objectUrl = window.URL.createObjectURL(file);
   printJS({
      printable: objectUrl,
      type: "image",
   });
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值