跳至页脚内容
PDF 工具

如何在 React 中将 HTML 转换为 PDF (开发者教程)

Converting HTML to PDF in React

在 React 中将 HTML 转换为 PDF 已成为许多 Web 应用程序的重要功能。 无论您是在构建发票系统、报告生成器,还是只需要以全局接受的格式共享信息,PDF 生成都是至关重要的。 在本文中,我们将探讨如何通过使用流行的库将 HTML 转换为 PDF 来在 React 应用程序中创建和样式化 PDF 文件。

class="hsg-featured-snippet">

如何在 React 中将 HTML 转换为 PDF

  1. 创建并配置一个 React 项目
  2. 使用 npm 下载将 HTML 转换为 PDF 的库
  3. 从 React-pdf/renderer 中导入必要的模块
  4. 使用导入的模块配置 HTML 页面
  5. 利用 React-pdf 的PDFDownloadLink模块将 HTML 转换为 PDF

PDF 生成的流行库

在深入了解将 HTML 转换为 PDF 的过程中之前,让我们先讨论一些可用于在 React 应用程序中PDF 生成的流行库:

  1. React-pdf:一个强大的库,用于在 React 应用程序中创建 PDF 文档。 它支持各种样式选项,可以轻松创建复杂的多页 PDF。
  2. jsPDF:一个广泛使用的 JavaScript 库,用于即时生成 PDF 文件。 它提供了广泛的功能,包括文本样式、图像嵌入等。
  3. html2canvas:此库允许您捕获 HTML 元素的屏幕截图并将其转换为画布对象,然后可以通过使用其他库(如 jsPDF)将其转换为 PDF。

在 React 中将 HTML 转换为 PDF 的前提条件

对 React 及其生态系统的熟悉

在深入了解 HTML 到 PDF 转换之前,拥有扎实的 React 基础是至关重要的。 这包括对 JSX、状态管理、组件生命周期和钩子的了解。

对 HTML、CSS 和 JavaScript 的理解

在使用 React-pdf 库时,强大的 HTML、CSS 和 JavaScript 基础至关重要。 这包括对 HTML 元素和属性、CSS 样式和选择器的了解,以及 JavaScript 基础知识,如变量、函数和循环。

开始一个 React 应用程序

在我们继续将HTML 转换为 React 中的 PDF之前,让我们快速浏览一下如何使用流行的create-react-app CLI 工具创建一个新的 React 应用程序。 这将是我们 PDF 生成示例的基础。

步骤 1 安装 Node.js

确保您在计算机上安装了 Node.js。您可以从官方 Node.js 网站下载最新版本的 Node.js。

步骤 2 安装 create-react-app

create-react-app 是一个广泛使用的 CLI 工具,用于生成 React 应用程序。 使用以下命令全局安装它:

npm install -g create-react-app
npm install -g create-react-app
SHELL

步骤 3 创建新的 React 应用程序

您现在安装了create-react-app,可以使用以下命令创建新的 React 应用程序:

create-react-app my-pdf-app
create-react-app my-pdf-app
SHELL

此命令将在名为my-pdf-app的文件夹中生成一个新的 React 应用程序。 进入新创建的目录:

cd my-pdf-app
cd my-pdf-app
SHELL

步骤 4 启动开发服务器

要启动开发服务器并看到您的新 React 应用程序运行效果,请运行以下命令:

npm start
npm start
SHELL

步骤 5 实现 PDF 生成

您现在已设置 React 应用程序,您可以遵循本文前面各节中概述的步骤,使用流行的库(如React-pdf)来实现HTML 到 PDF 转换

介绍 React-pdf 库

React-pdf 是专为 React 应用程序设计的流行库,提供与 React 生态系统的无缝集成。 它的一些关键功能包括支持内联和外部 CSS、多页 PDF 生成、先进的样式和与服务器端渲染(SSR)的兼容性。

使用 React-pdf 创建 PDF 文件

在本节中,我们将重点介绍在 React 应用程序中使用React-pdf创建 PDF 文件。 首先,您需要安装React-pdf包:

npm install --save @react-pdf/renderer
npm install --save @react-pdf/renderer
SHELL

安装后,您可以创建一个新的 React 组件来定义 PDF 文档的结构:

import React from 'react';
import {
  Document,
  Page,
  Text,
  View,
  StyleSheet
} from '@react-pdf/renderer';

// Sample invoice data
const invoiceData = {
  sender: {
    name: "John Doe",
    address: "123 Main Street",
    city: "New York",
    state: "NY",
    zip: "10001",
  },
  recipient: {
    name: "Jane Smith",
    address: "456 Elm Street",
    city: "San Francisco",
    state: "CA",
    zip: "94107",
  },
  items: [
    { description: "Item 1", quantity: 2, unitPrice: 10 },
    { description: "Item 2", quantity: 3, unitPrice: 15 },
    { description: "Item 3", quantity: 1, unitPrice: 20 },
  ],
  invoiceNumber: "INV-123456",
  date: "April 26, 2023",
};

// Define styles for PDF document
const styles = StyleSheet.create({
  page: {
    backgroundColor: "#FFF",
    padding: 30,
  },
  header: {
    fontSize: 24,
    textAlign: "center",
    marginBottom: 30,
  },
  sender: {
    marginBottom: 20,
  },
  recipient: {
    marginBottom: 30,
  },
  addressLine: {
    fontSize: 12,
    marginBottom: 2,
  },
  itemsTable: {
    display: "table",
    width: "100%",
    borderStyle: "solid",
    borderWidth: 1,
    borderRightWidth: 0,
    borderBottomWidth: 0,
  },
  tableRow: {
    margin: "auto",
    flexDirection: "row",
  },
  tableColHeader: {
    width: "25%",
    borderStyle: "solid",
    borderWidth: 1,
    borderLeftWidth: 0,
    borderTopWidth: 0,
    backgroundColor: "#F0F0F0",
  },
  tableCol: {
    width: "25%",
    borderStyle: "solid",
    borderWidth: 1,
    borderLeftWidth: 0,
    borderTopWidth: 0,
  },
  tableCell: {
    fontSize: 12,
    textAlign: "center",
    padding: 5,
  },
  total: {
    marginTop: 20,
    textAlign: "right",
  },
  totalLabel: {
    fontSize: 14,
    fontWeight: "bold",
  },
  totalValue: {
    fontSize: 14,
  },
});

const InvoiceDocument = () => {
  // Calculate total amount
  const totalAmount = invoiceData.items.reduce(
    (total, item) => total + item.quantity * item.unitPrice,
    0
  );

  return (
    <Document>
      <Page style={styles.page}>
        <Text style={styles.header}>Invoice</Text>
        <View style={styles.sender}>
          <Text>{invoiceData.sender.name}</Text>
          <Text>{invoiceData.sender.address}</Text>
          <Text>
            {invoiceData.sender.city}, {invoiceData.sender.state} {invoiceData.sender.zip}
          </Text>
        </View>
        <View style={styles.recipient}>
          <Text>{invoiceData.recipient.name}</Text>
          <Text>{invoiceData.recipient.address}</Text>
          <Text>
            {invoiceData.recipient.city}, {invoiceData.recipient.state} {invoiceData.recipient.zip}
          </Text>
        </View>
        <View style={styles.itemsTable}>
          <View style={styles.tableRow}>
            <Text style={[styles.tableColHeader, styles.tableCell]}>Description</Text>
            <Text style={[styles.tableColHeader, styles.tableCell]}>Quantity</Text>
            <Text style={[styles.tableColHeader, styles.tableCell]}>Unit Price</Text>
            <Text style={[styles.tableColHeader, styles.tableCell]}>Amount</Text>
          </View>
          {invoiceData.items.map((item, index) => (
            <View key={index} style={styles.tableRow}>
              <Text style={[styles.tableCol, styles.tableCell]}>{item.description}</Text>
              <Text style={[styles.tableCol, styles.tableCell]}>{item.quantity}</Text>
              <Text style={[styles.tableCol, styles.tableCell]}>{item.unitPrice.toFixed(2)}</Text>
              <Text style={[styles.tableCol, styles.tableCell]}>
                {(item.quantity * item.unitPrice).toFixed(2)}
              </Text>
            </View>
          ))}
        </View>
        <View style={styles.total}>
          <Text style={styles.totalLabel}>Total: ${totalAmount.toFixed(2)}</Text>
        </View>
      </Page>
    </Document>
  );
};

export default InvoiceDocument;
import React from 'react';
import {
  Document,
  Page,
  Text,
  View,
  StyleSheet
} from '@react-pdf/renderer';

// Sample invoice data
const invoiceData = {
  sender: {
    name: "John Doe",
    address: "123 Main Street",
    city: "New York",
    state: "NY",
    zip: "10001",
  },
  recipient: {
    name: "Jane Smith",
    address: "456 Elm Street",
    city: "San Francisco",
    state: "CA",
    zip: "94107",
  },
  items: [
    { description: "Item 1", quantity: 2, unitPrice: 10 },
    { description: "Item 2", quantity: 3, unitPrice: 15 },
    { description: "Item 3", quantity: 1, unitPrice: 20 },
  ],
  invoiceNumber: "INV-123456",
  date: "April 26, 2023",
};

// Define styles for PDF document
const styles = StyleSheet.create({
  page: {
    backgroundColor: "#FFF",
    padding: 30,
  },
  header: {
    fontSize: 24,
    textAlign: "center",
    marginBottom: 30,
  },
  sender: {
    marginBottom: 20,
  },
  recipient: {
    marginBottom: 30,
  },
  addressLine: {
    fontSize: 12,
    marginBottom: 2,
  },
  itemsTable: {
    display: "table",
    width: "100%",
    borderStyle: "solid",
    borderWidth: 1,
    borderRightWidth: 0,
    borderBottomWidth: 0,
  },
  tableRow: {
    margin: "auto",
    flexDirection: "row",
  },
  tableColHeader: {
    width: "25%",
    borderStyle: "solid",
    borderWidth: 1,
    borderLeftWidth: 0,
    borderTopWidth: 0,
    backgroundColor: "#F0F0F0",
  },
  tableCol: {
    width: "25%",
    borderStyle: "solid",
    borderWidth: 1,
    borderLeftWidth: 0,
    borderTopWidth: 0,
  },
  tableCell: {
    fontSize: 12,
    textAlign: "center",
    padding: 5,
  },
  total: {
    marginTop: 20,
    textAlign: "right",
  },
  totalLabel: {
    fontSize: 14,
    fontWeight: "bold",
  },
  totalValue: {
    fontSize: 14,
  },
});

const InvoiceDocument = () => {
  // Calculate total amount
  const totalAmount = invoiceData.items.reduce(
    (total, item) => total + item.quantity * item.unitPrice,
    0
  );

  return (
    <Document>
      <Page style={styles.page}>
        <Text style={styles.header}>Invoice</Text>
        <View style={styles.sender}>
          <Text>{invoiceData.sender.name}</Text>
          <Text>{invoiceData.sender.address}</Text>
          <Text>
            {invoiceData.sender.city}, {invoiceData.sender.state} {invoiceData.sender.zip}
          </Text>
        </View>
        <View style={styles.recipient}>
          <Text>{invoiceData.recipient.name}</Text>
          <Text>{invoiceData.recipient.address}</Text>
          <Text>
            {invoiceData.recipient.city}, {invoiceData.recipient.state} {invoiceData.recipient.zip}
          </Text>
        </View>
        <View style={styles.itemsTable}>
          <View style={styles.tableRow}>
            <Text style={[styles.tableColHeader, styles.tableCell]}>Description</Text>
            <Text style={[styles.tableColHeader, styles.tableCell]}>Quantity</Text>
            <Text style={[styles.tableColHeader, styles.tableCell]}>Unit Price</Text>
            <Text style={[styles.tableColHeader, styles.tableCell]}>Amount</Text>
          </View>
          {invoiceData.items.map((item, index) => (
            <View key={index} style={styles.tableRow}>
              <Text style={[styles.tableCol, styles.tableCell]}>{item.description}</Text>
              <Text style={[styles.tableCol, styles.tableCell]}>{item.quantity}</Text>
              <Text style={[styles.tableCol, styles.tableCell]}>{item.unitPrice.toFixed(2)}</Text>
              <Text style={[styles.tableCol, styles.tableCell]}>
                {(item.quantity * item.unitPrice).toFixed(2)}
              </Text>
            </View>
          ))}
        </View>
        <View style={styles.total}>
          <Text style={styles.totalLabel}>Total: ${totalAmount.toFixed(2)}</Text>
        </View>
      </Page>
    </Document>
  );
};

export default InvoiceDocument;
JAVASCRIPT

现在,您可以使用 PDFDownloadLink 组件来自 React-pdf,来下载生成的 PDF 文件:

import React from 'react';
import { PDFDownloadLink } from '@react-pdf/renderer';
import InvoiceDocument from './InvoiceDocument';
import './App.css';

const App = () => (
  <div className="app-container">
    <PDFDownloadLink
      document={<InvoiceDocument />}
      fileName="invoice.pdf"
      className="download-button"
    >
      {({ loading }) =>
        loading ? 'Loading document...' : 'Download Invoice'
      }
    </PDFDownloadLink>
  </div>
);

export default App;
import React from 'react';
import { PDFDownloadLink } from '@react-pdf/renderer';
import InvoiceDocument from './InvoiceDocument';
import './App.css';

const App = () => (
  <div className="app-container">
    <PDFDownloadLink
      document={<InvoiceDocument />}
      fileName="invoice.pdf"
      className="download-button"
    >
      {({ loading }) =>
        loading ? 'Loading document...' : 'Download Invoice'
      }
    </PDFDownloadLink>
  </div>
);

export default App;
JAVASCRIPT

现在在App.css中添加一些 CSS 样式以实现自定义 UI:

.app-container {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
  background-color: #d1e8ff;
}

.download-button {
  display: inline-block;
  background-color: #5a8fd5;
  color: #fff;
  font-size: 18px;
  font-weight: bold;
  padding: 12px 24px;
  border-radius: 4px;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 0.3s ease;
}

.download-button:hover {
  background-color: #3a68b7;
}

在浏览器中打开localhost:3000。 当您点击下载按钮时,PDF 文件将被下载。

样式化您的 PDF 文件

React-pdf 库支持一系列样式选项,与 CSS 类似。 以下是一些常用的样式属性,您可以用它们来自定义 PDF 文件的外观:

  • color:设置文本颜色。
  • fontSize:设置文本的字体大小。
  • fontFamily:设置文本的字体系列。
  • textAlign:设置文本对齐方式(例如,'left'、'right'、'center' 或 'justify')。
  • margin:设置元素周围的边距。
  • padding:设置元素内部的填充。
  • border:设置元素周围的边框。
  • backgroundColor:设置元素的背景颜色。

React 开发者的替代 PDF 库

IronPDF for Node.js 是在 React 中将 HTML 转换为 PDF 的一个绝佳替代方案。 由 Iron Software 开发,它是一个强大的库,允许开发人员直接从他们的 Node.js 应用程序生成和处理 PDF 文档。 其突出功能之一是在生成 PDF 时处理 HTML 内容中的 JavaScript 执行能力,从而实现动态和交互式 PDF 创建。

支持包括 Windows、MacOS、Linux、Docker 和像 Azure 和 AWS 这样的云平台,IronPDF 确保跨平台兼容性。 其用户友好的 API 允许开发人员快速将 PDF 生成和处理集成到他们的 Node.js 项目中。

React 是构建用户界面的 JavaScript 库,由于 IronPDF 是为 Node.js 构建的,您可以通过其 Node.js API 将 IronPDF 集成到您的 React 应用程序中。

以下是如何使用 IronPDF 和 React 的概要:

  1. 安装 IronPDF:您可以使用 npm 或 yarn 在 React 项目中安装 IronPDF。
npm install @ironsoftware/ironpdf
npm install @ironsoftware/ironpdf
SHELL
  1. 集成 React 组件:您可以创建利用 IronPDF 生成和处理 PDF 的 React 组件。 例如,您可以有一个组件,接收 HTML 内容作为输入并使用 IronPDF 的 API 将其转换为 PDF。
import React from 'react';
import { PdfDocument } from '@ironsoftware/ironpdf';

const HTMLToPDFComponent = () => {
    const convertHTMLToPDF = async (htmlContent) => {
        try {
            const pdf = await PdfDocument.fromHtml(htmlContent);
            await pdf.saveAs('generated_pdf.pdf');
            alert('PDF generated successfully!');
        } catch (error) {
            console.error('Error generating PDF:', error);
        }
    };

    return (
        <div>
            {/* Input HTML content */}
            <textarea onChange={(e) => convertHTMLToPDF(e.target.value)} />
        </div>
    );
};

export default HTMLToPDFComponent;
import React from 'react';
import { PdfDocument } from '@ironsoftware/ironpdf';

const HTMLToPDFComponent = () => {
    const convertHTMLToPDF = async (htmlContent) => {
        try {
            const pdf = await PdfDocument.fromHtml(htmlContent);
            await pdf.saveAs('generated_pdf.pdf');
            alert('PDF generated successfully!');
        } catch (error) {
            console.error('Error generating PDF:', error);
        }
    };

    return (
        <div>
            {/* Input HTML content */}
            <textarea onChange={(e) => convertHTMLToPDF(e.target.value)} />
        </div>
    );
};

export default HTMLToPDFComponent;
JAVASCRIPT
  1. 处理 PDF 生成:在您的 React 组件中使用 IronPDF 的功能以处理 PDF 生成、处理和保存。 You can use IronPDF's methods for converting HTML strings, URLs, or images to PDFs.
  2. 渲染 PDFs:一旦您使用 IronPDF 生成了 PDFs,您可以使用合适的组件或库在 React 应用程序中渲染它们以显示 PDF 文档。
import React from 'react';

const PDFViewerComponent = () => {
    return (
        <div>
            {/* Render PDF using appropriate component or library */}
            <iframe src="generated_pdf.pdf" width="100%" height="600px" title="PDF Viewer" />
        </div>
    );
};

export default PDFViewerComponent;
import React from 'react';

const PDFViewerComponent = () => {
    return (
        <div>
            {/* Render PDF using appropriate component or library */}
            <iframe src="generated_pdf.pdf" width="100%" height="600px" title="PDF Viewer" />
        </div>
    );
};

export default PDFViewerComponent;
JAVASCRIPT

通过 IronPDF,开发人员可以有效地从各种来源生成专业级 PDF 文档,将它们自定义以满足特定要求,并将 PDF 生成功能无缝集成到其 .NET 应用程序中。 IronPDF 还支持高级功能,如 CSS、JavaScript 和自定义字体,确保您生成的 PDF 文件将符合应用程序的设计和要求。

结论

在本文中,我们介绍了使用 React-pdf 库在 React 中将 HTML 转换为 PDF 的过程。 我们讨论了 PDF 生成 的流行库,如何使用 React-pdf 创建和样式化 PDF 文件,以及生成更复杂 PDF 文档的附加选项。

通过遵循本指南,您现在应该对如何在您的 React 应用程序中生成 PDF 文件有了一个全面的了解,能够生成高质量的 PDF 并满足各种用例需求。

IronPDF 提供 免费试用版,允许您测试库并确定其是否满足您的需求,然后再进行购买。 在试用期结束后,IronPDF 购买许可证 从 $799 开始,包括优先支持和更新。 Additionally, IronPDF is available for other languages like C# .NET, Java, and Python. 通过开始使用 IronPDF for Node.js 下载 IronPDF 库并尝试一下。

Darrius Serrant
全栈软件工程师(WebOps)

Darrius Serrant 拥有迈阿密大学的计算机科学学士学位,目前在 Iron Software 担任全栈 WebOps 市场工程师。从小就被编码吸引,他认为计算机既神秘又易于接触,使其成为创意和问题解决的理想媒介。

在 Iron Software,Darrius 喜欢创造新事物,并简化复杂概念以使其更易理解。作为我们常驻的开发者之一,他还自愿教授学生,与下一代分享他的专业知识。

对于 Darrius 来说,他的工作令人满意,因为它被重视并产生真正的影响。