跳過到頁腳內容
PDF工具

如何在 React 中將 HTML 轉換成 PDF(開發者教程)

在 React 中將 HTML 轉換為 PDF

在 React 中將 HTML 轉換為 PDF 已成為許多 Web 應用程式的必備功能。 無論您是建立發票系統、報表產生器,還是僅僅需要以通用格式共享訊息,PDF 生成都至關重要。 在本文中,我們將探討如何使用流行的程式庫將 HTML 轉換為 PDF,從而在 React 應用程式中建立和設定 PDF 文件樣式。

常用的 PDF 生成庫

在深入探討如何將 HTML 轉換為 PDF 之前,讓我們先來討論一些可以在 React 應用程式中用於產生 PDF 的常用程式庫:

  1. React-pdf :一個強大的程式庫,用於在 React 應用程式中建立 PDF 文件。 它支援多種樣式選項,可以輕鬆建立複雜的多頁 PDF 檔案。
  2. jsPDF :一個廣泛使用的 JavaScript 函式庫,用於動態產生 PDF 檔案。 它提供了多種功能,包括文字樣式設定、圖像嵌入等等。
  3. html2canvas :此程式庫可讓您擷取 HTML 元素的螢幕截圖並將其轉換為 canvas 對象,然後可以使用 jsPDF 等其他程式庫將其轉換為 PDF。

React 中將 HTML 轉換為 PDF 的前提條件

熟悉 React 及其生態系統

在深入研究 HTML 轉 PDF 之前,對 React 有紮實的了解至關重要。 這包括對 JSX、狀態管理、元件生命週期和鉤子函數的了解。

了解 HTML、CSS 和 JavaScript

要使用 React-pdf 函式庫,紮實的 HTML、CSS 和 JavaScript 基礎至關重要。 這包括對 HTML 元素和屬性、CSS 樣式和選擇器以及 JavaScript 基礎知識(如變數、函數和循環)的了解。

React 應用程式入門

在開始使用 React 將 HTML 轉換為 PDF之前,讓我們快速了解如何使用流行的create-react-app CLI 工具建立一個新的 React 應用程式。 這將作為我們產生 PDF 範例的基礎。

步驟 1:安裝 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-pdf在 React 應用程式中建立 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 :設定文字對齊方式(例如,"左對齊"、"右對齊"、"居中對齊"或"兩端對齊")。
  • margin :設定元素周圍的邊距。
  • padding :設定元素內部的內邊距。
  • border : 設定元素的邊框。
  • backgroundColor :設定元素的背景顏色。

面向 React 開發者的備選 PDF 函式庫

IronPDF for Node.js 是一個優秀的替代方案,可用於在 React 中將 HTML 轉換為 PDF。 該庫由 Iron Software 開發,功能強大,允許開發人員直接從其 Node.js 應用程式生成和操作 PDF 文件。 其突出特點之一是能夠在生成 PDF 時處理 HTML 內容中的 JavaScript 執行,從而實現動態和互動式 PDF 創建。

IronPDF 支援包括 Windows、MacOS、Linux、Docker 以及 Azure 和 AWS 等雲端平台在內的各種平台,確保跨平台相容性。 它易於使用的 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 的產生、操作和保存。 您可以使用 IronPDF 的方法將HTML 字串URL圖像轉換為 PDF。
  2. 渲染 PDF:使用 IronPDF 產生 PDF 後,您可以使用適當的元件或函式庫在 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起,其中包括優先支援和更新。 此外,IronPDF 還支援其他語言,如C# .NETJavaPython從 IronPDF for Node.js下載 IronPDF 庫,然後試試看。

Darrius Serrant
全棧軟件工程師 (WebOps)

Darrius Serrant 擁有邁阿密大學計算機科學學士學位,目前任職於 Iron Software 的全栈 WebOps 市場營銷工程師。從小就迷上編碼,他認為計算既神秘又可接近,是創意和解決問題的完美媒介。

在 Iron Software,Darrius 喜歡創造新事物,並簡化複雜概念以便於理解。作為我們的駐場開發者之一,他也自願教學生,分享他的專業知識給下一代。

對 Darrius 來說,工作令人滿意因為它被重視且有實際影響。