zoukankan      html  css  js  c++  java
  • html2canvas+jspdf实现下载pdf文件

    参考相关文章:

    https://blog.risingstack.com/pdf-from-html-node-js-puppeteer/

    https://juejin.im/post/5dae8b82e51d4524ce222764 这篇文章写得很好很具体了,下面记录下实际运用。

    关于页面导出 .pdf 格式文件:

      使用 window.print() 即可调出浏览器的在线打印功能,然后保存为 pdf 格式的文件,如果不想在页面弹出打印功能,可以把生成 pdf 放在后端处理,后端生成好 pdf 格式的文件,放在服务器上,然后提供给前端一个 api 地址,前端发起 api 请求去下载 pdf 文件,大概是这样的思路。

      但是本文记录是通过 html2canvas 将 HTML 页面转换成图片,然后通过 jspdf 将图片的 base64 生成 pdf 文件。

      代码环境:React + ts

      缺点:生成的 pdf 内容无法复制,因为是图片。

    1、安装 html2canvas 和 jspdf :

    npm install html2canvas jspdf

    2、新建一个文件,单独处理生成 pdf

    import html2canvas from 'html2canvas'
    import jsPdf from 'jspdf'
    
    async function htmlToPdf() {
      const elId: string = 'body' // body: 想要生成 pdf 的页面的id
      if (!elId) {
        // tslint:disable-next-line:no-console
        console.error('导出节点不存在!')
        return
      }
      // 将html dom节点生成canvas
      const htmlCanvas = await getCanvasByHtmlId(elId)
      // 将canvas对象转为pdf
      const pdf = canvasToPdf(htmlCanvas)
      // 通过浏览器下载pdf
      downPdf(pdf, '文件名')
    }
    
    /**
     *  @param elId 打印的节点ID
     */
    async function getCanvasByHtmlId(elId: string) {
      const elIdDom: any = document.getElementById(elId)
      const canvas: any = await html2canvas(elIdDom, {
        scale: 2,
        useCORS: true,
        allowTaint: true,
        // taintTest: false,
        imageTimeout: 0,
      }).then((canvas: any) => {
        return canvas
      })
    
      return canvas
    }
    
    /**
     *  @param htmlCanvas canvas对象
     */
    function canvasToPdf(htmlCanvas: any) {
      const canvasWidth = htmlCanvas.width
      const canvasHeight = htmlCanvas.height
      const imgBase64 = htmlCanvas.toDataURL('image/jpeg', 1.0)
    
      // a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
      const imgWidth = 595.28
      // 图片高度需要等比缩放
      const imgHeight = 595.28 / canvasWidth * canvasHeight
    
      let pageHeight = imgHeight // pdf转化后页面总高度
      let position = 0
    
      const pdfInstance = new jsPdf('', 'pt', 'a4')
      pdfInstance.setFontSize(12)
    
      if (imgHeight < 841.89) {
        pdfInstance.addImage(imgBase64, 'JPEG', 0, 0, imgWidth, imgHeight)
      } else {
        while (pageHeight > 0) {
          pdfInstance.addImage(imgBase64, 'JPEG', 0, position, imgWidth, imgHeight)
          pageHeight -= 841.89
          position -= 841.89
          if (pageHeight > 0) {
            pdfInstance.addPage()
          }
        }
      }
    
      return pdfInstance
    }
    
    function downPdf(pdfInstance: any, title: string) {
      // 文件名过长导致下载失败
      if (title.length > 50) {
        title = title.substring(title.length - 50)
      }
    
      pdfInstance.save(title + '.pdf', { returnPromise: true }).then(() => {
        // 搜狗浏览器下载机制问题暂时不关闭
        if (!(navigator.userAgent.toLowerCase().indexOf('se 2.x') > -1)) {
          setTimeout(window.close, 300)
        }
      })
    }
    
    export default htmlToPdf
    

      

    3、在页面调用

    import HtmlToPdf from './HtmlToPdf'
    
    
     <div onClick={HtmlToPdf}>下载</div>
    

      

    补充:

      其实还有另外一种方法更简便,但是缺点是无法等比缩放 pdf 的宽高度。你也可以结合上面的方法计算出等比缩放的宽和高。

    function printPDF () {
        const domElement: any = document.getElementById('body')
        html2canvas(domElement, { onclone: () => {
        }})
        .then((canvas: any) => {
            const img = canvas.toDataURL('image/png')
            const pdf = new jsPdf()
            pdf.addImage(img, 'JPEG', 0, 0, 230, 200) // 230, 200 自定义的
            pdf.save('your-filename.pdf')
        })
      }
    

       

  • 相关阅读:
    Mac卸载vue-cli2X 时失败: Missing write access to --如侦探小说般的解谜之路
    mac-coursera网站DNS污染的解决方案
    mac摄像头打不开的问题
    node-npm-webpack
    webpack报错 : Can't resolve '.distundle.js'
    npm Error: listen EADDRINUSE 127.0.0.1:8080
    常用mac终端命令
    mac下的环境变量配置- cnpm :command not found
    less安装 出错问题
    vue-devtools vue开发调试神器
  • 原文地址:https://www.cnblogs.com/zhangym118/p/13398847.html
Copyright © 2011-2022 走看看