跳過到頁腳內容
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. 下載用於在 React 中將 HTML 轉換為 PDF 的庫,使用 npm
  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

對 HTML、CSS 和 JavaScript 有一個堅實的基礎是使用 React-pdf 庫的基礎。 這包括對 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 轉換。

介紹 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

現在,您可以使用 React-pdf 中的 PDFDownloadLink 元件下載生成的 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 應用程式中。

以下是您可以在 React 中使用 IronPDF 的大綱:

  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. 渲染 PDF:一旦您使用 IronPDF 生成了 PDF,您可以在 React 應用程式中使用合適的元件或庫來渲染它們。
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 庫將 HTML 轉換為 React 中的 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 來說,工作令人滿意因為它被重視且有實際影響。