QuestPDF 文件產出指南
用途:以 Fluent API 在 .NET 中產生 PDF 文件,不需要 HTML 模板
NuGet:
QuestPDF(目前版本 2026.2.x)授權:Community License(年營收 < $1M USD 免費,否則需付費)
支援:.NET 6+、.NET 8+、.NET Standard 2.0
什麼是 QuestPDF
QuestPDF 是一個以 Fluent API 為核心的 .NET PDF 產生器。不同於 iTextSharp 的低階 API 或 HTML-to-PDF 的模板方式,QuestPDF 用 C# 程式碼直接描述文件版面,像在寫 UI Layout。
vs 其他方案
| 方案 | 授權 | 方式 | 中文支援 | 適合場景 |
|---|---|---|---|---|
| QuestPDF | Community / Professional | Fluent C# API | 需設定字體 | 報表、證書、標籤 |
| iTextSharp 7 | AGPL / 商用付費 | 低階 API | 好 | 複雜排版 |
| Puppeteer/Playwright | 免費 | HTML → PDF | 好 | 網頁轉 PDF |
| ClosedXML | MIT | Excel | N/A | 匯出 Excel 後印 |
| Crystal Reports | 商用 | 設計器 | 好 | 傳統報表 |
QuestPDF 的優勢:程式碼即文件——版面結構在 C# 中完整表達,易於版本控制、測試、動態產生。
授權說明
warning
QuestPDF 從 2024.3 版起改為 Community License:
- 年營收 < $1M USD 的公司:免費使用
- 年營收 ≥ $1M USD:需購買 Professional 或 Enterprise License
- 詳細條款請見 QuestPDF License
使用前請確認公司適用哪個層級。
安裝
dotnet add package QuestPDF
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;
// 設定授權類型(必須在產生 PDF 前呼叫)
QuestPDF.Settings.License = LicenseType.Community;
核心架構
QuestPDF 的內容模型是「Document → Page → Page Slot → 容器 → 元素」5 層嵌套。下圖把這 5 層展開,並把對應 API 標在每一層上:
各層職責對照:
| 層 | 主要 API | 負責什麼 |
|---|---|---|
| Document | Document.Create(...) / .GeneratePdf("file.pdf") | 整份 PDF 的入口;可同時設定 metadata |
| Page | container.Page(page =>) + page.Size(...) / page.Margin(...) / page.DefaultTextStyle(...) | 一張頁面的尺寸、邊距、預設樣式 |
| Page Slot | page.Header() / page.Content() / page.Footer() | 三個固定槽位;只有 Content 會自動分頁,Header/Footer 每頁重複 |
| 容器 | Column / Row / Stack / Decoration | 子內容的排列方向與空間分配 |
| 葉節點元素 | Text / Image / Table | 實際畫到 PDF 上的內容 |
讀圖重點:
- Page Slot 是固定的 3 個(Header / Content / Footer),不能多也不能少;要做封面 / 目錄通常用第一頁的 Content +
PageBreak()處理,而非額外開 slot。 - 容器可以無限巢狀(
Column → Row → Column → Row都沒問題),但Page Slot與Element兩層不可省略 — slot 直接放Text也可以,但通常會包一個 Column / Row 容器以便擴充。 - Element 是葉節點:再往下的細節(如
Text.Span/Table.Cell/Image.FitArea)屬於元素內部 API,不是另一層巢狀容器。
最小範例
QuestPDF.Settings.License = LicenseType.Community;
Document.Create(container =>
{
container.Page(page =>
{
page.Size(PageSizes.A4);
page.Margin(2, Unit.Centimetre);
page.Header().Text("設備參數報表")
.FontSize(20).Bold().FontColor(Colors.Blue.Darken2);
page.Content().Column(col =>
{
col.Item().Text($"產出日期:{DateTime.Now:yyyy/MM/dd}");
col.Item().PaddingTop(10).Text("溫度:85.3°C");
col.Item().Text("壓力:2.4 MPa");
col.Item().Text("轉速:1500 RPM");
});
page.Footer().AlignCenter()
.Text(x =>
{
x.Span("第 ");
x.CurrentPageNumber();
x.Span(" / ");
x.TotalPages();
x.Span(" 頁");
});
});
})
.GeneratePdf("設備報表.pdf");
中文字體設定
QuestPDF 預設不含中文字體,需要明確指定:
// 註冊自訂字體
FontManager.RegisterFont(File.OpenRead("NotoSansCJKtc-Regular.otf"));
// 或使用系統字體
Document.Create(container =>
{
container.Page(page =>
{
page.DefaultTextStyle(style =>
style.FontFamily("Microsoft JhengHei") // 微軟正黑體
.FontSize(10));
// ... 內容
});
});
tip
建議將字體檔案打包到應用程式中(如 Embedded Resource 或 Content 檔案),避免依賴系統安裝字體。生產環境(如 Docker Linux)可能沒有中文字體。
本指南結構
| 頁面 | 內容 |
|---|---|
| 概觀(本頁) | 定位、授權、安裝、入門 |
| 元件與版面 | Row、Column、Table、Text、Image、Header/Footer |
| 報表 Pattern | 標準報表模板、動態表格、多語系、批次產出 |