前端生成pdf文件并下载

1,035 阅读2分钟

这篇文章主要是记录了前端生成pdf文件并下载功能的实现,这个功能的实现用到了html2canvasjsPDF

一、实现思路:

1、使用html2canvas将指定容器内的html转为canvas,

2、将canvas转成base64的图片数据

3、使用jsPDF将图片数据插入到pdf页面中

二、实现过程

1、安装

npm install html2canvas
npm install jspdf

2、封装一个公用方法:useCompToPDF.ts
注:这个方法的具体实现是取自网友们分享的方法,来源~

import html2canvas from 'html2canvas';
import jsPDF from "jspdf";

interface CompToPDFProps {
  fileName: string;
}

 const PDFFile = {
   A4:[592.28, 841.89]
 }

const useCompToPDF = (props: CompToPDFProps) => {

  const { fileName } = props

  const exportPDF = (element: HTMLElement | null) => {

    if (element) {

      html2canvas(element, {
        backgroundColor: null,
        allowTaint: true,
        useCORS: true,
        scale: 2,
      }).then((canvas) => {

        // 获取画布的宽高
        let canvasWidth = canvas.width
        let canvasHeight = canvas.height

        // 一页pdf显示HTML生成的canvas高度
        let pdfPageHeight = (PDFFile.A4[1] / PDFFile.A4[0]) * canvasWidth

        // 未生成pdf的html页面内的高度
        let pdfAllHeight = canvasHeight

        // 页面偏移
        let position = 0
        let pageData = canvas.toDataURL('image/jpeg', 1.0)

        let imgWidth = PDFFile.A4[0] - 60
        let imgHeight = (canvasHeight / canvasWidth) * PDFFile.A4[0]

        let pdf = new jsPDF('p', 'pt', PDFFile.A4)

        if (pdfAllHeight < pdfPageHeight) {

           pdf.addImage(pageData, 'JPEG', 30 ,0, imgWidth, imgHeight)

         } else {

           while (pdfAllHeight > 0) {

             pdf.addImage(pageData, 'JPEG', 30, position, imgWidth, imgHeight)

             pdfAllHeight -= pdfPageHeight

             position -= PDFFile.A4[1]

            if (pdfAllHeight > 0) {
               pdf.addPage()
            }
          }
         }
         pdf.save(`${fileName}.pdf`)
      })
    }
  }

  return {
    exportPDF
  }
}

export default useCompToPDF

3、使用

import useCompToPDF from './useCompToPDF';

export default function Page() {

const { exportPDF } = useCompToPDF({fileName:'haha.pdf'})

return (
    <Fragment>
    
    <button onClick={() => {
        let target = document.getElementById('pdfBox');
        exportPDF(target)
    }>下载</button>
    <div
        style={{
          backgroundColor: '#ffffff',
          position: 'absolute',
          left: -1000,
        }}
        id="pdfBox"
      ></div>
    </Fragment>

  );

}
}

三、遇到的问题

在实现的过程中,我遇到了以下两个问题:

1、canvas中一片空白,没有预期的网页内容

原因:目标容器的高度设置为0了,或者设置display:none等方式使目标内容在页面上不可见,这会导致转为canvas时内容空白的问题。

解决方式:如果目标元素并不需要展示在页面上,那么可以使用绝对定位的方式,让它“消失”。

2、html2canvas返回的canvas 的背景是黑色的。虽然已经按照官方文档设置了backgroundColor属性,但仍然没起作用。

解决方式:无意间增加设置了scale属性,背景色就正常了。如果你也遇到了同样的问题,那这也不妨是一个解决的方式。不过虽然问题解决了,但是不是很明白为什么设置了scale就正常了,有了解的小伙伴欢迎帮我解惑吖~

四、遗留问题

还有一个问题,就是如果生成的图片很长,一页放不下,那图片会被截断显示在不同页上,截断的位置就有可能会把某行文字截断,这个问题目前还没有找到合适的解决方案。 不知道你有没有合适的解决方案呢,希望能够分享给我吖~

ok, 本篇就先记录这么多。

320e85a2500b48cfb14a350a163c63fa~tplv-k3u1fbpfcp-zoom-in-crop-mark 1512 0 0 0.webp