发布时间:2023-04-25 文章分类:WEB开发, 电脑百科 投稿人:王小丽 字号: 默认 | | 超大 打印

国庆突如其来的加班q.q,上午接到的需求,只能起床啦

自己也是第一次接触这种业务需求,进行了一顿cv大法,网上有很多版本,个人学习借鉴(cv)了一下,在这里做个学习记录,欢迎各位指正优化,参考学习,如有侵权立即删除。

printDialog.vue(PDF使用弹窗展示,确认btn打印)

HTML

<template>
  <div>
    <el-dialog title="打印" :visible.sync="dialogVisible" width="50%">
        <div class="box">
          <pdf ref="pdf" :src="pdfUrl"></pdf>
        </div>
      <span slot="footer" class="dialog-footer">
        <el-button @click="dialogVisible = false">取 消</el-button>
        <el-button
          type="primary"
        @click="$refs.pdf.print()"
          >确 定</el-button
        >
      </span>
    </el-dialog>
  </div>
</template>

js

<script>
//插件vue-pdf-signature
import pdf from "vue-pdf-signature";
import CMapReaderFactory from "vue-pdf-signature/src/CMapReaderFactory.js";
export default {
    components: {
    pdf,
  },
  data() {
    return {
      dialogVisible: false,
      pdfUrl:''
    };
  },
  methods:{
      init(res){
          this.dialogVisible = true;
          this.getObjectURL(res)
      },
      // 将返回的文件流数据转换为url(data: 文件流数据)
    getObjectURL(data) {
      let url = null;
      let file = new Blob([data], { type: "application/pdf" });
      if (window.createObjectURL != undefined) {
        // 通用
        url = window.createObjectURL(file);
      } else if (window.webkitURL != undefined) {
        // 兼容谷歌
        try {
          url = window.webkitURL.createObjectURL(file);
        } catch (error) {}
      } else if (window.URL != undefined) {
        // 兼容其他
        try {
          url = window.URL.createObjectURL(file);
        } catch (error) {}
      }
      //这里是重点,将处理的url使用CMapReaderFactory方法在进行处理
      url = pdf.createLoadingTask({ url: url, CMapReaderFactory });
      // 将转化后url赋值
      this.pdfUrl = url;
    },
  }
};
</script>

父组件.vue(btn点击)

HTMl

<el-button size="small" type="primary" @click="subscriptionPrinting()"
          >打印</el-button>
//弹窗
<print-dialog ref="printDialog" ></print-dialog>

js

<script>
import printDialog from "./printDialog.vue";
export default {
  components: {
    printDialog,
  },
  methods:{
  subscriptionPrinting() {
      this.$http
        .get(
          `请求~~~`,
          {
            responseType: "blob",//这个必须带
          }
        )
        .then(({ data: res }) => {
          this.$refs['printDialog'].init(res);
        });
    },
  }
</script>

以上就是全部代码了,坑还是比较多的以下来进行总结

1.插件的使用

  使用的是vue-pdf-signature而不是vue-pdf,是因为vue-pdf在第一次正常打开会正常显示,第二次打开会显示空白,控制台会提示报错(Error during font loading: Failed to execute 'postMessage' on 'Worker': ArrayBuffer at index 0 is already detached),vue-pdf-signature是大佬针对vue-pdf出现的这一问题进行的改良版。细看可前往大佬链接~

vue-pdf踩坑指南_快进小树林的博客-CSDN博客

2.不显示中文

  通过引入CMapReaderFactory.js解决,但是引入会出现1所描述的问题,所以采用了vue-pdf-signature进行解决(崇拜大佬ing)

3.向后端请求解析失败问题(显示空白,控制台提示报错)

  在请求中添加{
             responseType: "blob",//这个必须带
            }即可解决。

  请求回的文件流所做的数据处理在上面代码有注释,详看翻上

4.打印调用$refs.pdf.print()即可。

*补:PDF多页不展示问题

在处理返回流的方法(getObjectURL)中,this.numPages在data中

getObjectURL(data) {
      let url = null;
      let file = new Blob([data], { type: "application/pdf" });
      if (window.createObjectURL != undefined) {
        // 通用
        url = window.createObjectURL(file);
      } else if (window.webkitURL != undefined) {
        // 兼容谷歌
        try {
          url = window.webkitURL.createObjectURL(file);
        } catch (error) {}
      } else if (window.URL != undefined) {
        // 兼容其他
        try {
          url = window.URL.createObjectURL(file);
        } catch (error) {}
      }
      //这里是重点,将处理的url使用CMapReaderFactory方法在进行处理
      url = pdf.createLoadingTask({ url: url, CMapReaderFactory });
      url.promise.then(pdf=>{
        this.unmPages = pdf.numPages
      // 将转化后url赋值
      this.pdfUrl = url;
    },

html处

<div class="box">
    <pdf ref="pdf" :src="pdfUrl" v-for="item in numPages" :key="index" :page="item"></pdf>
</div>
<el-button
          type="primary"
        @click="$refs.pdf[0].print()"
          >打 印</el-button
        >

处理pdf多页不展示问题