• Vue PDF文件预览vue-pdf


       最近做项目,遇到预览PDF这个功能,在网上找了找,大多推荐的是pdf.js,不过在Vue中还是想偷懒直接npm组件,最后找到了一个还不错的Vue-pdf 组件,GitHub地址:https://github.com/FranckFreiburger/vue-pdf#readme
    不过一般GitHub上的注释比较简洁,所以这里把自己实际使用的过程总结了一下,下面贴代码
     
     本博客源码: https://github.com/shengbid/vue-demo  这个项目里会把平时博客写的一些功能的代码都放在里面,有需要可以下载看看,有帮助的话点个star哈
     
    引用: npm install --save vue-pdf
     
    template代码:
    <template>
      <div class="pdf" v-show="fileType === 'pdf'">
        <p class="arrow">
        // 上一页
        <span @click="changePdfPage(0)" class="turn" :class="{grey: currentPage==1}">Preview</span>
        {{currentPage}} / {{pageCount}}
        // 下一页
        <span @click="changePdfPage(1)" class="turn" :class="{grey: currentPage==pageCount}">Next</span>
        </p>
        // 自己引入就可以使用,这里我的需求是做了分页功能,如果不需要分页功能,只要src就可以了
        <pdf
          :src="src" // src需要展示的PDF地址
          :page="currentPage" // 当前展示的PDF页码
          @num-pages="pageCount=$event" // PDF文件总页码
          @page-loaded="currentPage=$event" // 一开始加载的页面
          @loaded="loadPdfHandler"> // 加载事件
        </pdf>
      </div>
    </template>
    js代码:<script>  // 引入PDF
      import pdf from 'vue-pdf'
      export default {
        components: {pdf},
        data () {
          return {
            currentPage: 0, // pdf文件页码
            pageCount: 0, // pdf文件总页数
            fileType: 'pdf', // 文件类型
         src: '', // pdf文件地址
    } },
      created: {
        // 有时PDF文件地址会出现跨域的情况,这里最好处理一下
        this.src = pdf.
    createLoadingTask(this.src)
      }
        method: {
          // 改变PDF页码,val传过来区分上一页下一页的值,0上一页,1下一页
          changePdfPage (val) {
            // console.log(val)
            if (val === 0 && this.currentPage > 1) {
              this.currentPage--
              // console.log(this.currentPage)
            }
            if (val === 1 && this.currentPage < this.pageCount) {
              this.currentPage++
              // console.log(this.currentPage)
            }
          },
    
          // pdf加载时
          loadPdfHandler (e) {
            this.currentPage = 1 // 加载的时候先加载第一页
          }
    
        }
      }
    
    </script>

    实际效果

    问题补充:  文件打印乱码问题解决方法

    之前有人问了关于PDF打印乱码问题,我自己试了确实有这个问题,在官网找了一下,有人提交了代码解决了这个问题,现在我把方法附上

    原始的打印页面,PDF格式乱码,主要是因为PDF里使用了自定义字体,不能识别

    需要修改vue-pdf安装包的pdfjsWrapper.js文件

    上面后缀为1的文件是原始的,红线框起来的是我修改之后的文件

    替换之后,打印就能正常显示了,

    博客园貌似不能上传文件,代码太多就不放上来了,如果有需要可以找我邮箱发你,或者到官网自己修改文件

    git-hup地址:https://github.com/FranckFreiburger/vue-pdf/pull/130/commits/253f6186ff0676abf9277786087dda8d95dd8ea7,

     上面提供的解决文件打印乱码的问题,实现起来比较麻烦,而且现在vue-pdf的版本已经更新了,用这个方法可能还会出现空白页的问题.自己在研究了下,用了iframe来预览打印,效果会更好些,这里把方法放上来,有需要的可以试试

    这里的例子是把PDF文件放在elment的弹框中,当然你可以根据你自己的适用场景来决定

    html:

    <el-dialog
              :close-on-click-modal="false"
              :visible.sync="dialogVisible"
              :fullscreen="true"
              title="文件预览">
              <div class="agreement_picture">
                <div class="pdf">
                  <!-- <pdf // 之前的用PDF插件的方法
                    v-for="i in pdf.numPages"
                    :key="i"
                    :page="i"
                    :src="src">
                  </pdf> -->
                  // 使用iframe方法
                  <iframe :src="src" frameborder="0" style=" 100%; height: 100%"></iframe>
                </div>
              </div>
              <span slot="footer" class="dialog-footer">
                <div class="tip-left transfer">
                    <el-button type="info" @click="dialogVisible=false">不同意</el-button>
                  <el-button type="danger" @click="agreeSignFun">同意</el-button>
                </div>
              </span>
            </el-dialog>    

    js:

      data () {
        return {
          src: '/static/file/中国互联网整体网民发展状况——《第31次中国互联网发展状况调查报告(上)》.pdf', //pdf地址,这里我用的是我本地的文件,你也可以使用后台的文件
          dialogVisible: true
        }
      }

    效果展示:

    打印效果:

     

    补充内容:

    朋友们,关于跨域问题,我这里说明一下,如果你是在本地localhost环境请求后台接口返回的文件地址,一般都会跨域,报错如下

    这个文件地址我在浏览器可以直接打开预览

    遇到这种问题,是因为你本地的localhost和你后台返回的域名不一致,可以先用一个本地静态文件调试效果,在线上环境即通过打包部署的环境(域名和返回的PDF域名一致的环境)再看效果.如果域名端口一致的情况还有报跨域的错误,那你的项目与vue-pdf八字不合,建议更换组件

    另外补充一下打印的问题,通过vue-pdf自带的打印功能,打印出来的效果一般是这样

    这个作者在git上也说了,现在vue-pdf的打印功能还在试验阶段,没有完善,所以寄希望于这个方法实现打印还需一段时日,上面的内容里我用了<iframe>标签来预览打印,但是现在iframe已经不怎么使用了,有些项目还不允许用,这里我再补充两种打印方法

    1. 先把PDF内容转成图片后再打印

    <el-dialog
          title="文件预览"
          :visible.sync="dialogVisible"
          width="50%"
        >
          <div ref="printContent">
            <!-- 加载全部页面的PDF是循环生成,不能指定ref,不能调用print打印方法 -->
            <Pdf
              v-for="i in numPages"
              :key="i"
              :src="src"
              :page="i"
            />
            <!-- 写一个隐藏的PDF,用来调用打印 -->
            <Pdf
              v-show="false"
              ref="printPdf"
              :src="src"
            />
          </div>
          <span slot="footer" class="dialog-footer">
            <el-button @click="print">vue-pdf自带打印</el-button>
            <el-button type="primary" @click="toImg">转图片打印</el-button>
          </span>
        </el-dialog>
    <script>
    import Pdf from 'vue-pdf'
    import html2canvas from 'html2canvas'
    import printJS from 'print-js'
    
    export default {
      components: {
        Pdf
      },
      data() {
        return {
          fileList: [
            {
              id: 1,
              fileName: '增进函',
              fileUrl: 'http://172.16.79.33:8888/group1/.........../rBBPIV7whg2AQNCmAAoc6DKtkwE841.pdf'
            },
            {
              id: 2,
              fileName: '应收账款',
              fileUrl: `${window.location.origin}/test1.pdf`
            }
          ],
          numPages: undefined,
          dialogVisible: false,
          src: '',
          printName: '转图片打印'
        }
      },
      created() {
    
      },
      methods: {
        // 预览
        preview(item) {
          this.src = Pdf.createLoadingTask(item.fileUrl)
          this.src.promise.then(pdf => {
            this.numPages = pdf.numPages
          })
          this.dialogVisible = true
          this.printName = item.fileName
        },
        // 转图片打印
        toImg() {
          html2canvas(this.$refs.printContent, {
            backgroundColor: null,
            useCORS: true,
            windowHeight: document.body.scrollHeight
          }).then((canvas) => {
            const url = canvas.toDataURL()
            printJS({
              printable: url,
              type: 'image',
              documentTitle: this.printName
            })
            // console.log(url)
          })
        },
    
        // pdf自带打印
        print() {
          this.$refs.printPdf.print()
        }
      }
    }

    打印效果

    2.跳转页面打印,这种和iframe的差不多,新建一个页面,调用window.print()打印页面,效果如下

     

    最近我会把vue-pdf的使用整理一下,把源码放到git上,之前的代码找不到了

     如果以上都不能解决你的问题,我觉得你可以使用window.open()直接新页面打开预览,使用浏览器自带的打印预览功能.如果产品不同意,你可以对他晓之以情,动之以理

    现在一般项目为了安全性,不会直接返回文件地址,会返回文件流的格式,对于文件流格式文件可以转化成blob文件,如果有需要可以看下我另一篇博客:文件流数据如何转blob文件 https://www.cnblogs.com/steamed-twisted-roll/p/11821148.html

  • 相关阅读:
    PHP获取一周的日期
    关系型数据库和非关系型数据库的区别和特点
    关系型数据库和非关系型数据库的特性以及各自的优缺点
    什么是数据库?什么是关系数据库?什么是非关系型数据库?
    PHP中把对象转数组的几个方法
    验证银行卡号
    xss过滤方法
    PHP 随机字符
    计算两个日期相差年月日
    判断一个时间段是否包含周末
  • 原文地址:https://www.cnblogs.com/steamed-twisted-roll/p/9648255.html
Copyright © 2020-2023  润新知