首页 > 技术文章 > html2pdf.js之长页面html转PDF导出

lovecode3000 2020-11-19 17:04 原文

长页面html转PDF导出

html转pdf的用法网上教程搜索一大堆,但公司遇到新需求,需要把6000条数据转为pdf,页面会变空白,后端推前端,前端推后端,那我们就自己研究下吧

网上教程我随便找了一条,https://www.jianshu.com/p/56680ce1cc97 如果直接不是长页面参考这个教程即可
为什么打印不了的原因,在html2pdf.js中渲染过程是由html转称canvas,再由canvas转成pdf,作者明确指出在html5中canvas具有最大高度和宽度,超出最大限度便无法进行打印

canvas最大限度示例

Chrome:
Maximum height/width: 32,767 px
Maximum area: 268,435,456 px (例如, 16,384 x 16,384)

Firefox:
Maximum height/width: 32,767 px
Maximum area: 472,907,776 px (例如, 22,528 x 20,992)

IE:
Maximum height/width: 8,192 px
Maximum area: N/A

IE Mobile:
Maximum height/width: 4,096 px
Maximum area: N/A

那么我们知道了原因,可不可以将页面拆分为较小的区块,然后将它们单独添加到 PDF 中呢?
答案是可以的。

使用注意

  1. 打印前需要滚动到页面顶部,不然打印页面会出现一段空白
  2. 需要引用以下文件
    // "jspdf.min.js"
    // "html2canvas.min.js"
    // "html2pdf.min.js"
    //单纯使用js时,按照以上顺序引用,不然canvas会把pdf覆盖

    //使用vue时
    //安装  npm install --save html2pdf.js
    //引用只需要引用html2pdf.js即可   import html2pdf.js from 'html2pdf.js';
    //因为html2pdf.js自动引用了jspdf和canvas
  1. 在使用element ui框架时,内容在Dialog弹窗中时无法正常打印。
    可以尝试使用divEle.cloneNode(true)拷贝一份添加到body上,再进行打印pdf
  2. 如果打印的内容不清楚,可以使用scale:2来调节,但会增加文件大小

代码示例

<button id="downpdf">按钮</button>
<div id='divEle'>
      <ul>
            //我是数据
      </ul>
      <ul>
            //我是数据
      </ul>
      <!-- 重复ul内容 -->
</div>

  <script src="https://cdn.bootcdn.net/ajax/libs/es6-promise/4.2.8/es6-promise.auto.min.js"></script>
  <script src="./node_modules/jspdf/dist/jspdf.min.js"></script>
  <script src="./node_modules/html2canvas/dist/html2canvas.js"></script>
  <script src="./node_modules/html2pdf.js/dist/html2pdf.js"></script>

  <script>
  //文档地址:https://ekoopmans.github.io/html2pdf.js/    
  var downpdfEle = document.querySelector('#downpdf');

    downpdfEle.onclick = function () {
      //超出canvas限度打印
      var pages = document.querySelector('#divEle').children;
      exportHTMLToPDF(pages,'模板')
      //正常打印
      //htmlToPdf('#divEle','模板')
    }

    //超出canvas限度打印函数
    function exportHTMLToPDF(pages,name) {
      const opt = {
        margin: [0, 0],
        filename: name+'.pdf',
        image: {
          type: 'jpeg',
          quality: 0.98
        },
        html2canvas: {
          dpi: 192,      
          scale:2,
          letterRendering: true
        },
        jsPDF: {
          unit: 'mm',
          format: 'a4',
          orientation: 'landscape'
        }
      };


      var worker = html2pdf()

      for (let i = 0; i < pages.length; i++) {
        console.log(pages[i]);
        worker = worker.set(opt).from(pages[i]).toContainer().toCanvas().toPdf().get('pdf').then((pdf) => {
          if (i < pages.length - 1) { // Bump cursor ahead to new page until on last page
            pdf.addPage();
          }
        });
      }
      worker.save();
    }


    //正常打印
   function htmlToPdf(el,name) {   //('#divEle',模板)
      let ele = document.querySelector(el);

      let opt = {
        margin: 1,
        filename:  name+'.pdf',
        image: {
          type: 'jpeg',
          quality: 0.98
        },
        html2canvas: {
          scale: 2,
          dpi: 92,
        },
        jsPDF: {
          unit: 'in',
          format: 'letter',
          orientation: 'portrait'
        }
      };
      html2pdf().set(opt).from(ele).save();
    }
  </script>    

推荐阅读