从 React Components 生成 PDF 文件

IT技术 reactjs pdf meteor
2021-04-05 04:49:49

我一直在构建一个投票应用程序。人们能够创建他们的民意调查并获取有关他们提出的问题的数据。我想添加功能,让用户以 PDF 的形式下载结果。

例如,我有两个组件负责获取问题和数据。

<QuestionBox />
<ViewCharts />

我正在尝试将两个组件输出到 PDF 文件中。然后用户可以下载这个 PFD 文件。我发现了一些允许在组件内呈现 PDF 的包。但是,我未能找到可以从包含虚拟 DOM 的输入流生成 PDF 的方法。如果我想从头开始实现这一目标,我应该遵循什么方法?

6个回答

将react渲染为 pdf 通常很痛苦,但有一种使用画布的方法。

这个想法是转换:HTML -> Canvas -> PNG(或 JPEG) -> PDF

要实现上述目标,您需要:

  1. html2canvas &
  2. jsPDF

import React, {Component, PropTypes} from 'react';

// download html2canvas and jsPDF and save the files in app/ext, or somewhere else
// the built versions are directly consumable
// import {html2canvas, jsPDF} from 'app/ext';


export default class Export extends Component {
  constructor(props) {
    super(props);
  }

  printDocument() {
    const input = document.getElementById('divToPrint');
    html2canvas(input)
      .then((canvas) => {
        const imgData = canvas.toDataURL('image/png');
        const pdf = new jsPDF();
        pdf.addImage(imgData, 'JPEG', 0, 0);
        // pdf.output('dataurlnewwindow');
        pdf.save("download.pdf");
      })
    ;
  }

  render() {
    return (<div>
      <div className="mb5">
        <button onClick={this.printDocument}>Print</button>
      </div>
      <div id="divToPrint" className="mt4" {...css({
        backgroundColor: '#f5f5f5',
        width: '210mm',
        minHeight: '297mm',
        marginLeft: 'auto',
        marginRight: 'auto'
      })}>
        <div>Note: Here the dimensions of div are same as A4</div> 
        <div>You Can add any component here</div>
      </div>
    </div>);
  }
}

该代码段在此处不起作用,因为未导入所需的文件。

此答案中使用了另一种方法,其中删除了中间步骤,您可以简单地从 HTML 转换为 PDF。在jsPDF文档中也有一个选项可以这样做,但是从个人观察来看,我觉得先将dom转换为png会获得更好的准确性。

更新 0:2018 年 9 月 14 日

通过这种方法创建的 pdf 上的文本将无法选择。如果这是一个要求,您可能会发现这篇文章很有帮助。

通过这种方法可以复制创建的pdf上的文本吗?
2021-06-02 04:49:49
一样。将您的内容放在 div 列表中。每个 div 代表一张 a4 纸(将 css 添加到 div 以复制边距)。然后在每个 div 上运行打印功能。
2021-06-05 04:49:49
@ShivekKhurana 我的 div 根据屏幕大小而变化,但我希望 PDF 文件始终相同,而不取决于窗口大小。反正我能做到吗?另外,我如何导入 {...css} ?
2021-06-07 04:49:49
在您的回答的帮助下,我已经成功地从 html 页面创建了一个 PDF 文件。但是如果我们想创建一个包含多个页面的 PDF 那么怎么办?a4 尺寸的页面在所有边都有适当的边距,并且在每个新页面中都应该应用边距。请帮我它的银色。先感谢您。我在这里创建了一个问题question
2021-06-08 04:49:49
@Goutham 答案是否定的:PDF 的内容是位图图像
2021-06-08 04:49:49

您可以使用 jsPDF 来使用画布

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

 _exportPdf = () => {

     html2canvas(document.querySelector("#capture")).then(canvas => {
        document.body.appendChild(canvas);  // if you want see your screenshot in body.
        const imgData = canvas.toDataURL('image/png');
        const pdf = new jsPDF();
        pdf.addImage(imgData, 'PNG', 0, 0);
        pdf.save("download.pdf"); 
    });

 }

你用 id 捕获的 div 是:

例子

<div id="capture">
  <p>Hello in my life</p>
  <span>How can hellp you</span>
</div>
为什么要添加答案的副本?
2021-05-26 04:49:49
此解决方案的唯一问题是它将捕获 div 的整个图像,但会生成包含其中一部分的 pdf - 而不是完整的。特别是当 div 太宽时。简单的解决方法是更换两条线。一个是 jspdf 构造函数行const pdf = new jsPDF('p', 'pt', 'a4', false);,第二个将在 pdf 行上粘贴图像pdf.addImage(imgData, 'PNG', 0, 0, 600, 0, undefined, false);如果要调整 pdf 中捕获图像的宽度或高度,请使用 addImage 函数的第 5 个参数。疯了:P
2021-06-20 04:49:49
图片质量不好,生成的pdf有a4边的部分被剪掉了,这个结果对于react-to-pdf和jdpdf库都是一样的
2021-06-21 04:49:49

只需几步。我们可以从我们的 HTML 页面下载或生成 PDF,或者我们可以从 HTML 页面生成特定 div 的 PDF。

步骤:HTML -> 图像(PNG 或 JPEG) -> PDF

请按照以下步骤操作,

步骤1 :-

npm install --save html-to-image
npm install jspdf --save

第2步 :-

/* ES6 */
import * as htmlToImage from 'html-to-image';
import { toPng, toJpeg, toBlob, toPixelData, toSvg } from 'html-to-image';
 
/* ES5 */
var htmlToImage = require('html-to-image');

-------------------------
import { jsPDF } from "jspdf";

第 3 步:-

   ******  With out PDF properties given below  ******

 htmlToImage.toPng(document.getElementById('myPage'), { quality: 0.95 })
        .then(function (dataUrl) {
          var link = document.createElement('a');
          link.download = 'my-image-name.jpeg';
          const pdf = new jsPDF();          
          pdf.addImage(dataUrl, 'PNG', 0, 0);
          pdf.save("download.pdf"); 
        });


    ******  With PDF properties given below ******

    htmlToImage.toPng(document.getElementById('myPage'), { quality: 0.95 })
        .then(function (dataUrl) {
          var link = document.createElement('a');
          link.download = 'my-image-name.jpeg';
          const pdf = new jsPDF();
          const imgProps= pdf.getImageProperties(dataUrl);
          const pdfWidth = pdf.internal.pageSize.getWidth();
          const pdfHeight = (imgProps.height * pdfWidth) / imgProps.width;
          pdf.addImage(dataUrl, 'PNG', 0, 0,pdfWidth, pdfHeight);
          pdf.save("download.pdf"); 
        });

我认为这很有帮助。请试试

链接和link.download 是必须的吗?
2021-06-11 04:49:49

React-PDF是一个很好的资源。

将您的标记和 CSS 转换为 React-PDF 的格式有点费时,但很容易理解。导出和导出 PDF 相当简单。

要允许用户下载由 react-PDF 生成的 PDF,请使用他们的动态渲染,它提供了一个可定制的下载链接。单击时,站点会为用户呈现和下载 PDF。

这是他们的REPL,它将让您熟悉所需的标记和样式。他们也有 PDF 的下载链接,但他们没有在此处显示代码。

您可以使用 ReactDOMServer 将您的组件呈现为 HTML,然后在 jsPDF 上使用它。

首先做进口:

import React from "react";
import ReactDOMServer from "react-dom/server";
import jsPDF from 'jspdf';

然后:

var doc = new jsPDF();
doc.fromHTML(ReactDOMServer.renderToStaticMarkup(this.render()));
doc.save("myDocument.pdf");

更喜欢使用:

渲染到静态标记

代替:

渲染到字符串

由于前者包括react所依赖的 HTML 代码。

看起来很有趣,但是 renderToStaticMarkup 不返回任何样式,所以据我所知 jsPDF 只是呈现原始 html 的一些默认布局,除非有某种方法可以注入 css 类?
2021-06-01 04:49:49