使用jsPdf将HTML转换为PDF在React应用程序中无法工作

4

我正在使用React作为前端应用程序,想要使用jsPdf将React组件的一部分导出为PDF文件。

const handleDownload = () => {
  const content = document.getElementById('download-content');
  const doc = new jsPDF();
  doc.html(content);
  doc.save("a4.pdf");
}

React的返回组件是:

return (
<body>
  <header id='download-content'>
    <div>l kldfjlkasjfld asjflkajf ljfasd'flksdasjf lsdasjfsadf</div>
    <div>l kldfjlkasjfld asjflkajf ljfasd'flksdasjf lsdasjfsadf</div>
    <div>l kldfjlkasjfld asjflkajf ljfasd'flksdasjf lsdasjfsadf</div>
    <div>l kldfjlkasjfld asjflkajf ljfasd'flksdasjf lsdasjfsadf</div>
    <div>l kldfjlkasjfld asjflkajf ljfasd'flksdasjf lsdasjfsadf</div>
    <div>l kldfjlkasjfld asjflkajf ljfasd'flksdasjf lsdasjfsadf</div>
  </header>
  <footer>
    <button onClick={handleDownload}>Download</button>
  </footer>
</body>
)

点击 下载 按钮后,我希望得到一个包含 header 标签数据及样式的 PDF 文件。但是使用 handleDownload 函数时,我得到了一个空白的 PDF 文件。

我不想使用画布生成图像,然后再制作 PDF 文件。如果使用画布,当页面大小缩小时,PDF 文件将会改变。

如何获取与生成的 HTML 页面完全相同的 PDF 文件呢?

3个回答

6

两个注意事项:

  1. 在React中访问DOM元素时,应始终使用useRef

  2. 似乎.html方法是异步的并且需要一个回调函数

一个可用的示例代码如下:

import { useRef } from 'react';
import { jsPDF } from 'jspdf';

export default function PDF() {
    const pdfRef = useRef(null);

    const handleDownload = () => {
        const content = pdfRef.current;

        const doc = new jsPDF();
        doc.html(content, {
            callback: function (doc) {
                doc.save('sample.pdf');
            }
        });
    };

    return (
        <div>
            <header ref={pdfRef}>
                <div>l kldfjlkasjfld asjflkajf ljfasd'flksdasjf lsdasjfsadf</div>
                <div>l kldfjlkasjfld asjflkajf ljfasd'flksdasjf lsdasjfsadf</div>
                <div>l kldfjlkasjfld asjflkajf ljfasd'flksdasjf lsdasjfsadf</div>
                <div>l kldfjlkasjfld asjflkajf ljfasd'flksdasjf lsdasjfsadf</div>
                <div>l kldfjlkasjfld asjflkajf ljfasd'flksdasjf lsdasjfsadf</div>
                <div>l kldfjlkasjfld asjflkajf ljfasd'flksdasjf lsdasjfsadf</div>
            </header>
            <footer>
                <button onClick={handleDownload}>Download</button>
            </footer>
        </div>
    );
}

更新

如果您需要控制大小,可以根据上面提到的文档添加其他属性:

选项1-使用html2canvas选项并控制比例:

const handleDownload = () => {
    const content = pdfRef.current;

    const doc = new jsPDF();
    doc.html(content, {
        callback: function (doc) {
            doc.save('sample.pdf');
        },
        html2canvas: { scale: 0.5 } // change the scale to whatever number you need
    });
};

选项 2 - 使用 widthwindowWidth

const handleDownload = () => {
    const content = pdfRef.current;

    const doc = new jsPDF();
    doc.html(content, {
        callback: function (doc) {
            doc.save('sample.pdf');
        },
        width: 200, // <- here
        windowWidth: 200 // <- here
    });
};

谢谢。但完整的 div 标签没有显示出来。它被截断了一半的内容。我该如何正确地获取所有内容。 另外,当我进行响应式设计时,内容在 PDF 中不保持原样。它也变成了响应式的...但我希望它像全页视图一样标准。 - Jhon Arab
根据文档,您可以根据需要添加widthwindowWidth。请查看更新后的答案。 - SakoBu
@JhonArab 基本上,您需要查看库提供的所有选项并找出如何根据您的需求使用它... - SakoBu
非常感谢您。您真是太棒了。 - Jhon Arab
嘿@SakoBu,如果我想在此回调内添加一个页面到文档中,该怎么办?谢谢! - andremello

1
// use can you ReactDOMServer.renderToString(element) 

import { renderToString } from "react-dom/server";
import { jsPDF } from "jspdf";
export const dow = () => {
  let htmlElement = <div>Hello </div> 
  let elementAsString = renderToString(htmlElement);
  var doc = new jsPDF();
  doc.html(elementAsString, {
    callback: function (doc) {
      doc.save("test.pdf");
    },
    x: 10,
    y: 10,
  });
};

// use can use this code as function to handle an event 

0
如果我正确理解了你的问题,
这是我对你的问题的处理方法:
 const handleDownload = ()=>{
//content retrieves the element.
let content  = document.getElementById("download-content")
/*
 content2 retrieves the HTML code using ".outerHTML" as a string , 
 then add a line break between two opening tags, 
 as well as a line break between a closing tag and an opening tag 
 with the use of .replace and regexp
 */
let content2 = content.outerHTML.replace(/<(\w+)>(.*?)/g, '\n<$1>\n$2').replace(/(<\/\w+>)/g, '\n$1\n')
var doc = new jsPDF()
// This allows adding text to a PDF. 
doc.text(content2, 10 , 10)
doc.save("a4.pdf")

}

我希望这个回复能满足您的需求。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接