1.使用npm下载两个插件

a.将html页面转换成图片
npm install --save html2canvas 
b.将图片生成pdf
npm install jspdf --save

或者直接使用cdn

<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/0.5.0-alpha1/html2canvas.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.3.4/jspdf.min.js"></script> 

html部分

<template>
  <div class="">
    <div @click="downLoadPdf">下载pdf文件</div>
    <!--  -->
    <button type="button" class="btn btn-primary" v-on:click="getPdf()">导出PDF分页</button>
    <div class="pdf_warp">
      <div id="pdfDom">
        <h1>vue项目中使用pdf.js预览pdf文件(流)</h1>
        <p class="">
          好一段时间没有来简书写东西了,因为来到了平安银行(橙信)工作了,工作也比较忙,上班也没得外网,最近公司给配置了一个mac电脑,终于可以有外网权限了,但还是有很多限制,微信,百度云盘等等吧,都用不了,
          最近项目中需要显示保险的电子保单,但给的地址是一个pdf文件流,遇到了各种问题,跨域、android手机打不开......,最终选择了pdf.js插件,viewer.html?file=的形式打开,下面详情介绍一下开发步骤,
          
        </p>
        <p>一、 首先是导入插件,从官网直接下载,链接:官网直接下载,在vue项目中,注意放在static文件目录下</p>
        <div class="img_warp">
          <img src="../../../assets/4369687-c90a77c68fc6e04a.webp" alt="">
        </div>
        <p>简单介绍一下pdf.js目录,核心的pdf.js和pdf.worker.js,以及展示pdf的viewer.html页面,把它们作为静态资源来编译,基本想要的build和web这两个重要文件夹的东西都正常编译。</p>
        <p>二、重点介绍一下viewer.html?file=打开pdf文件</p>
        <p>1、打开viewer.js看看</p>
        <div class="js_warp">
          <p>"use strict";</p>
          <p>var DEFAULT_URL = 'compressed.tracemonkey-pldi-09.pdf';</p>
          <p>var pdfjsWebApp = void 0;</p>
        </div>
        <p>里面有配置项,DEFAULT_URL 是默认的pdf路径,继续看源代码,发现他可以通过file参数用来指定pdf的路径</p>
        <p>用viewer.html?file= 的方式,我是iframe进行嵌套</p>
        <!-- <div class="js_warp">
          <p><iframe :src="url" width="100%" height="100%"></iframe></p>
        </div> -->
        <p>2、当viewer.html页面的域和pdf文件域不一致的时候,会报 “file origin does not match viewer”错误。 所以我们得改变一下源码</p>
        <div class="img_warp">
          <img src="../../../assets/cw1.webp" alt="">
        </div>
        <p>3、file=后面跟的pdf地址也有参数,所以必须选择 encodeURIComponent 进行对url的编码</p>
        <div class="js_warp">
          <p>this.url = `${baseUrl.pageRoot}pdf/web/viewer.html?file=${encodeURIComponent(pdfUrl)}`</p>
        </div>
        <p>viewer.js里有方法parseQueryString(query)取到这个pdf文件地址后,会进行decodeURIComponent解码</p>
        <p>4、如果还是打不开pdf文件,pdf.js插件可能无法识别pdfUrl,所以的在最后加上 &.pdf 来骗过插件</p>
        <p>Q: 目前还遇到一个问题,GET请求pdfUrl时,cookie信息没有带给后端,目前是让后端直接屏蔽了登录验证,请各位指教。GET请求源码如下:</p>

        <h1>vue3基础</h1>
        <h2>一、setup</h2>
        <p>1.setup函数可以被理解为函数的入口</p>
        <p>2.setup函数接收两个参数:props、context(包含attrs、slots、emit)</p>
        <p>3.setup函数是处于生命周期函数 beforeCreate之前执行,执行setup函数时组件实例并未被创建,this不指向vue实例</p>
        <p>4.与模板一起使用:须在ref或reactive中声明然后return出去使用才是响应式的</p>
        <p>5.使用渲染函数:可以返回一个渲染函数,该函数可以直接使用在同一作用域中声明的响应式状态</p>
        <h2>二、setup第一个参数props</h2>
        <p>props 是响应式的,当传入新的 prop 时,它将被更新。</p>
        <div class="js_warp">
          <p>export default {</p>
          <p>props: {</p>
          <p>title: String</p>
          <p> },</p>
          <p>setup(props) {</p>
          <p>console.log(props.title)</p>
          <p>}</p>
          <p>}</p>
        </div>
        <h2>因为 props 是响应式的,不能使用 ES6 解构,会消除 prop 的响应性。</h2>
        <p>如果需要解构 prop,可以在 setup 函数中使用 [toRefs]函数来完成此操作:</p>
        <div class="js_warp">
          <p>setup(props) {</p>
          <p> const { title } = toRefs(props)</p>
          <p> return{ title  }</p>
          <p> },</p>
        </div>
        <h2>三、setup第二个参数context</h2>
        <p>context 是一个普通 JavaScript 对象,暴露了其它可能在 setup 中有用的值</p>
        <div class="js_warp">
          <p>setup(props, context) {</p>
          <p>// Attribute (非响应式对象,等同于 $attrs)</p>
          <p>console.log(context.attrs)</p>
          <p> // 插槽 (非响应式对象,等同于 $slots)</p>
          <p>console.log(context.slots)</p>
          <p>// 触发事件 (方法,等同于 $emit)</p>
          <p>console.log(context.emit)</p>
          <p>// 暴露公共 property (函数)</p>
          <p>console.log(context.expose)</p>
          <p>}</p>
        </div>
        <h2>context不是响应的,可以用ES6进行解构</h2>

        <div ref="footer"></div>
      </div>
    </div>
 
  </div>
</template>
dom转pdf-转出内容

可以有两种方式导出 

引入基础模块

import html2canvas from 'html2canvas'
import jsPDF from 'jspdf'
  data() { 
    return {
      htmlTitle: '页面导出PDF文件名',  //这个也是固定写法,pdf文件下载的名称
  },

  1:第一种不分页面

 methods:{
  // 下载pdf文件 不分页
    downLoadPdf(){
        window.scrollTo(0, 0);  
        const element = document.querySelector('#pdfDom')  ;// 这个dom元素是要导出pdf的div容器
        setTimeout(() => { 
          html2canvas(element, {  
            height: this.$refs.footer.offsetTop,
            useCORS: true // 如果说所生成的页面中带有跨域的图片,这个useCors需要设置为True 否则画布被污染不会显示
          }).then((canvas) => {
            console.log(canvas);
            const contentWidth = canvas.width;
            const contentHeight = canvas.height;
            // 一页pdf显示html页面生成的canvas高度;
            const pdfX = (contentWidth + 100) / 2 //* 0.975;
            const pdfY =  (contentHeight + 100) / 2 //* 0.975;// 500为底部留白
            const imgX = pdfX;
            const imgY = (contentHeight / 2);// 内  * 0.75
            const pageData = canvas.toDataURL('image/png', 1.0);
            const pdf = new jsPDF('', 'pt', [pdfX, pdfY]);
            // 有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89)
            // 内容未超过pdf一页显示的范围,无需分页
            pdf.addImage(pageData, 'png', 0, 0, imgX, imgY);
            pdf.save(12 + '.pdf'); // 生成的文件名字
          })
        },10)
    },
}

导出效果:

 

 

 

 2:第二种 导出pdf分页

 methods:{
    
    // 下载pdf文件 分页
    getPdf(){
      var title = this.htmlTitle
      html2canvas(document.querySelector('#pdfDom'), {
        allowTaint: true,
        useCORS: true
      }).then(function (canvas) {
        let contentWidth = canvas.width
        let contentHeight = canvas.height
        let pageHeight = contentWidth / 592.28 * 841.89
        let leftHeight = contentHeight
        let position = 0
        let imgWidth = 595.28
        let imgHeight = 580.28 / contentWidth * contentHeight
        let pageData = canvas.toDataURL('image/jpeg', 1.0)
        let PDF = new jsPDF('', 'pt', 'a4')
        if (leftHeight < pageHeight) {
          PDF.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight)
        } else {
          while (leftHeight > 0) {
            PDF.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight)
            leftHeight -= pageHeight
            position -= 841.89
            if (leftHeight > 0) {
              PDF.addPage()
            }
          }
        }
        PDF.save(title + '.pdf')
      }
      )
    },
}

导出效果:

 

posted on 2022-02-23 14:50  刘世涛6192  阅读(1049)  评论(0编辑  收藏  举报