該頁面可以包含自動翻譯的文字。

.NET PDF 產生器

借助 Docotic.Pdf,您可以利用頁面、容器、文字跨區、圖像、連結、頁首、頁尾、表格、清單等結構元素來產生 PDF 文件。這些元素可透過 Docotic.Pdf 的免費 Layout 插件提供的 Layout 高級 API 存取。該 API 還支援可重複使用的自訂元件。

Docotic.Pdf 如何產生 PDF 的範例:您排列圖像、表格和文字等元素,庫會根據該佈局產生 PDF

Layout API 可讓您使用流暢的方式,完全使用 C# 或 VB.NET 程式碼定義文件。基於此描述,該外掛程式提供的 PDF 產生器可以產生佈局任意複雜的文檔,從簡單的頁面到結構高度複雜的 PDF 報告,無所不能。

PDF產生基礎知識

要使用 Layout API 產生 PDF 文檔,您需要免費的 Layout 外掛程式。使用核心庫和插件也需要許可證金鑰。您可以使用免費試用金鑰或已購買的金鑰。

安裝插件

建議的安裝方式是透過 NuGet 安裝該插件。

Install-Package BitMiracle.Docotic.Pdf.Layout

軟體包管理器會自動處理依賴項。

如果您希望手動安裝此插件,請先下載包含 Docotic.Pdf 二進位檔案的 ZIP 壓縮檔。解壓縮後,加入以下 DLL 檔案的引用:

  • BitMiracle.Docotic.Pdf.dll
  • BitMiracle.Docotic.Pdf.Layout.dll(位於 Layout add-on 子資料夾中)。

取得許可證密鑰

要試用該庫,請填寫 Docotic.Pdf 下載頁面上的表格,申請一個免費的限時許可證金鑰。如果您已經購買了許可證,請使用購買後收到的代碼。

Layout 外掛程式是免費的,無需額外許可證。您可以使用現有的 Docotic.Pdf 授權來使用 Layout API。

Hello, world! 使用 Layout API

以下是使用 API 產生包含經典「Hello, world!」短語的 PDF 的範例程式碼:

BitMiracle.Docotic.LicenseManager.AddLicenseData("PUT-LICENSE-HERE");

PdfDocumentBuilder.Create().Generate("hello.pdf", doc => doc.Pages(pages =>
{
    pages.Content().Text("Hello, world!");
}));

這段程式碼會產生一個單頁 PDF 文件,文字位於左上角。

理解程式碼範例

範例首先新增許可證密鑰。沒有許可證,Docotic.Pdf 庫將不會產生任何內容。 PDF 產生程式碼從下一行開始。

程式碼透過呼叫靜態方法 PdfDocumentBuilder.Create() 來建立文件建構器的實例。呼叫 Generate 方法啟動 PDF 產生過程。此方法接受兩個參數:要產生的檔案名稱和一個類型為 Action<Document> 的委託。插件會產生 hello.pdf 作為 Generate 呼叫的結果。

為了確定 PDF 的佈局,文件建構器會使用 Document 實例呼叫委託。委託的程式碼會產生文檔內容。在本範例中,委託使用 Pages 方法向建構器提供另一個定義文件頁面佈局的委託。

建構器使用 Pages 實例呼叫傳遞給 Pages 方法的委託。此實例表示文件中的一個或多個頁面。頁面的具體數量取決於添加到其中的內容。

頁面委託會呼叫 Content 方法來存取頁面主要內容的佈局容器。透過鍊式呼叫容器的 Text 方法,可以將範例文字 span 新增到頁面中。有關佈局容器的詳細工作原理,請參閱佈局容器指南。

文件建構器會自動將內容拆分到多個頁面中,建立與新增至主要內容佈局容器的所有資料所需的頁面數量完全相同的頁面。在本範例中,單頁就足夠了,因此輸出結果恰好包含一個頁面。

基本範例以外的常見任務

範例程式碼首先建立一個 PdfDocumentBuilder 實例,然後呼叫 Generate 方法產生 PDF 檔案。您可以在生成器開始產生 PDF 之前對其進行配置。

例如,您可以透過向生成器提供加密處理程序來產生加密的 PDF 檔案。您也可以指定生成器要包含在產生的文件中的元資料。有關如何自訂生成器的更多詳細信息,請參閱單獨的文章。

範例程式碼僅使用主內容槽的佈局容器,但其他內容槽也可用。以下是用於存取內容槽的 PageLayout 方法的完整清單:

  • Background() - 傳回背景層,該層會被其他內容覆蓋。
  • Header() - 傳回所有頁面的公共頁首。
  • Content() - 返回主頁內容槽。
  • Footer() - 傳回所有頁面的公共頁腳。
  • Foreground() - 傳回前景層,該層會顯示在其他內容之上。

只有主內容槽中的內容才會影響產生的 PDF 的頁數。文件產生器會在每一頁上重複使用 Content() 提供的插槽之外的所有槽。有關內容槽的更多信息,請參閱關於頁面佈局的文章。

許多文件會在不同的頁面上使用不同的佈局。例如,第一頁可能採用封面式設計,而後續頁面則使用更簡潔的佈局。有些文件包含用於表格的特殊頁面,或根據不同的章節應用不同的背景。若要使用 Docotic.Pdf 和 Layout 外掛程式產生此類文檔,請多次呼叫 Document.Pages 方法。您可以在我們的範例庫中找到工作範例

程式碼整理

對於像範例中那樣的短程式碼,鍊式呼叫和嵌套 lambda 表達式是可以接受的。但當建立更複雜的程式時,將程式碼拆分成多個方法會更方便。這樣可以使程式碼更易於閱讀和維護。

以下是將 Hello, world! 範例程式碼拆分成多個方法後的樣子。

public void GeneratePdf()
{
    BitMiracle.Docotic.LicenseManager.AddLicenseData("PUT-LICENSE-HERE");

    PdfDocumentBuilder.Create().Generate("hello.pdf", BuildDocument);
}

private void BuildDocument(Document doc)
{
    doc.Pages(BuildPages);
}

private void BuildPages(PageLayout pages)
{
    pages.Content().Text("Hello, world!");
}

為什麼要使用 Docotic.Pdf Layout API 產生 PDF

Layout API 是一種對開發者友好且現代化的方式,它允許開發者使用可組合的構建塊生成 PDF,而無需了解 PDF 格式的內部機制。它能夠有效率且確定性地、可預測地佈局 PDF。您可以在高容量文件產生場景中使用此 API。

當 Docotic.Pdf 與免費的 Layout 插件一起使用時,即可使用此 API。 Docotic.Pdf 和 Layout 外掛程式均為 100% 託管程式碼的 DLL,不包含任何不安全的程式碼區塊。 Layout API 的實作無需任何第三方外部依賴項,例如瀏覽器或 Skia 二進位文件,從而打造出一個輕量級、低開銷的解決方案,易於部署和維護。

API概述

Layout API 是一款流暢易用的 API。您可以使用靈活的佈局元素,完全透過程式碼描述文件佈局,生成器會自動處理內容,進行分頁,並將結果渲染為 PDF。

Layout 外掛程式採用宣告式、基於流程的佈局系統。其佈局元素包括清單、列、行、表格、圖像、文字跨度、頁首和頁尾、容器等等。您無需手動將元素放置在精確的座標位置,只需描述元素的行為即可。文件建構器隨後會計算最終佈局並產生 PDF。

基於流程的佈局系統確保佈局能夠適應頁面大小和內容。得益於此系統,該插件在處理複雜、結構化、基於規則的佈局方面表現出色。您可以嵌套不同類型的容器,建立複雜的結構,而不會犧牲可讀性。

使用 Layout API 時,您可以將大多數呼叫連結在一起。與傳統 API 相比,這可以產生更簡潔、更具表現力的程式碼。調用鏈中的順序至關重要。所有程式碼都採用強型,確保編譯時安全,並方便重構。您也可以對使用 Layout API 的程式碼進行單元測試。

為了讓您的佈局實作更加簡潔,您可以擴展 API 並添加自訂方法,並圍繞它建立一個清晰、富有表現力的 DSL。

有關定位和 DSL 創建的更多信息,請參閱解釋如何控制容器的大小、位置、對齊方式和渲染行為的文章。

.NET 版本和平台支持

您可以在 .NET Standard 2.1 及更高版本框架的專案中使用 Layout API。換句話說,Layout 插件相容 .NET 5 到 .NET 10。此外,它還支援 .NET Core 3.0 及更高版本。

您可以使用 Layout API 在 ASP.NET Core、MAUI 應用程式、Unity、Xamarin 和控制台應用程式中產生 PDF。 Docotic.Pdf 配合 Layout 外掛程式可以在 Windows、macOS 和 Linux 系統上產生 PDF。

雲端平台和 Docker 映像

Docotic.Pdf 及其 Layout 外掛程式可在 Azure 和 AWS 雲端環境(包括無伺服器架構)中運作。此函式庫和外掛程式完全支援動態硬體變更、自動縮放和其他雲端原生運行時特性。

在大多數雲端場景中,需要使用 Unbound 授權。許可證常見問題解答解釋瞭如何選擇適用於雲端應用程式的授權

Layout API 可以直接在 Docker 容器中運作。在容器內運行庫和 Layout 外掛程式時,無需任何特殊配置即可產生 PDF 檔案。

在 PDF 文件中添加文本

文字是任何 PDF 文件的基本組成部分。您可以使用 LayoutContainer 類別的 Text 方法為內容槽新增文字。

文件頁面範例,周圍環繞著標題、說明文字、普通文字、超連結、加粗文字和腳註等文字樣式範例

文字跨度

在「Hello, world」範例中,我使用了 LayoutContainer.Text(string) 重載方法為頁面的主要內容新增文字。現在讓我們來看看 Text 方法的另一個重載方法。

public static void GenerateTextPdf()
{
    PdfDocumentBuilder.Create().Generate("text-spans.pdf", doc => doc.Pages(pages =>
    {
        pages.Content().Text(AddTextSpans);
    }));
}

private static void AddTextSpans(TextContainer text)
{
    text.Line("About VB.NET")
        .Style(t => t.Strong);

    text.Span("VB.NET is a multi-paradigm, object-oriented language ");
    text.Span("that runs on .NET, Mono, and the ");
    text.Hyperlink(
        ".NET Framework",
        new Uri("https://dotnet.microsoft.com/download/dotnet-framework"));
    text.Line(".");

    text.Span("Released by Microsoft in 2002, ");
    text.Line("it continues the lineage of the original Visual Basic language.");
}

這段程式碼使用 TextContainer 類別的 SpanLine 方法為目前行新增文字。 Line 方法也會補全目前行。範例程式碼也使用 Hyperlink 方法將外部資源連結附加到特定的文字 span 元素。

請注意範例程式碼如何使用 Style 方法對第一行套用強格式。接下來,我們將更詳細地探討文字樣式的概念。

文字樣式

文字樣式可讓您自訂文字的外觀。 TextStyle 類別提供了用於更改字體大小、字間距、顏色和其他文字屬性的方法。 TextStyle 物件是不可變的,因此每次方法呼叫都會產生一個新的樣式實例。您可以在不同的版面配置層級套用文字樣式。

PdfDocumentBuilder.Create().Generate("text-styles.pdf", doc =>
{
    doc.Pages(pages =>
    {
        pages.TextStyle(TextStyle.Parent.FontSize(30));

        pages.Content()
            .TextStyle(TextStyle.Parent.FontColor(new PdfRgbColor(0, 0, 255)))
            .Text(text =>
            {
                text.Span("Hello,");

                text.Span("World!")
                    .Style(TextStyle.Parent.Underline());
            });
    });
});

TextStyle.Parent 屬性傳回一個特殊樣式,其中所有文字屬性均未定義。在上面的範例中,程式碼使用 30 磅字體大小,以藍色繪製“Hello, World!”,第二個單字帶有下劃線。

這是因為程式碼:

  • 在頁面層級將字體大小設定為 30 磅,
  • 然後,將主要內容槽的文字顏色設為藍色,
  • 然後將下劃線樣式套用於最後一個文字跨度。

每個後續樣式都透過 TextStyle.Parent 屬性繼承先前的樣式。

使用 TextStyle 類別的方法,您可以變更文字方向(例如,從右到左)。請參閱我們範例庫中關於使用文字樣式繼承的另一個範例。

排版

TextStyle 類別支援自訂除關聯字型之外的所有文字屬性。若要變更預設字體,請使用 Document.TextStyleWithFont 方法建立基於特定字體的文字樣式。您可以使用作業系統中已安裝的字體,也可以從檔案或串流載入字體。

建立基於字體的樣式後,您可以套用其他可選屬性,然後將產生的樣式套用至文字跨度。以下 C# 範例示範如何使用系統字體。

PdfDocumentBuilder.Create().Generate("text-style-with-font.pdf", doc =>
{
    var font = SystemFont.Family("Calibri");
    var style = doc.TextStyleWithFont(font).FontSize(30);

    doc.Pages(pages =>
    {
        pages.Content().Text(text =>
        {
            text.Span("Hello,");

            text.Span("World!")
                .Style(style);
        });
    });
});

TextStyleWithFont 方法包含一個選用參數,用於指定字型在產生的文件中的嵌入方式。預設情況下,該庫:

  • 嵌入 TrueType/OpenType 字型的已用字形,
  • 嵌入 Type1 和 CFF 字型的所有字形,
  • 不嵌入內建 PDF 字體(Base14 字體)的字形。

由於這些預設設置,即使使用大字體,使用 TrueType 和 OpenType 字體的文件也可能保持較小的體積。您也可以指定自訂字體載入器、備用字體以及缺失字形的處理程序。有關管理 PDF 文件中字體的詳細信息,請參閱我們範例儲存庫中的範例程式碼。

Layout API 提供了一系列預定義樣式,您可以透過 Typography 類別存取和修改這些樣式。

PdfDocumentBuilder.Create().Generate("typography.pdf", doc =>
{
    doc.Typography(t =>
    {
        var fontsPath = Environment.GetFolderPath(Environment.SpecialFolder.Fonts);
        var arialFont = new FileInfo(Path.Combine(fontsPath, "arial.ttf"));

        t.Document = doc.TextStyleWithFont(arialFont);
        t.Header = t.Parent.FontSize(20).FontColor(new PdfGrayColor(20));
        t.Footer = t.Footnote;
    });

    doc.Pages(pages =>
    {
        pages.Header().AlignCenter().Text("Header");

        pages.Content().Text(t =>
        {
            t.Line("Title").Style(t => t.Title);
            t.Line("Heading 1").Style(t => t.Heading1);
            t.Line("Regular");
        });

        pages.Footer()
            .Height(20)
            .AlignCenter()
            .Text(t => t.CurrentPageNumber());
    });
});

我建議透過配置整個文件的排版來覆蓋預先定義的樣式,但這並非強制要求,您仍然可以在文字跨度層級套用文字樣式。

使用 Typography 類,您無需將文字樣式引用儲存在變數中。相反,您可以使用 Document.Typography 方法註冊所需的樣式,然後透過 Typography 物件的屬性存取它們。請參閱排版範例,以了解如何在產生 PDF 文件時使用預先定義和自訂文字樣式

許多實際應用中的 PDF 文檔,例如報告或發票,都包含頁首和頁尾。本節將介紹如何為 PDF 新增頁首和頁尾。

public static void GeneratePdfWithHeaderAndFooter()
{
    PdfDocumentBuilder.Create()
        .Generate("header-footer.pdf", doc => doc.Pages(pages =>
    {
        pages.Size(PdfPaperSize.A6).Margin(10);

        BuildPagesHeader(pages.Header());
        BuildPagesFooter(pages.Footer());

        pages.Content().Text("Hello, world!");
    }));
}

public static void BuildPagesHeader(LayoutContainer header)
{
    header.TextStyle(TextStyle.Parent.FontSize(8))
        .AlignRight()
        .Text(t =>
        {
            t.Line($"Created by: {Environment.UserName}");
            t.Line($"Date: {DateTime.Now}");
        });
}

public static void BuildPagesFooter(LayoutContainer footer)
{
    footer.AlignRight().Text(text =>
    {
        text.Style(t => t.Parent.FontColor(new PdfRgbColor(255, 0, 0)));

        text.CurrentPageNumber();
        text.Span(" / ");
        text.PageCount();
    });
}

BuildPagesHeader 方法會為頁眉文字設定較小的字體大小。頁首內容使用兩行:一行顯示目前使用者名,另一行顯示目前日期。文字右對齊。

請注意,程式碼沒有明確指定頁首的大小。頁眉佔據頁面寬度減去左右邊距後的全部寬度,其高度取決於文字行的高度。

BuildPagesFooter 方法示範如何在 PDF 頁腳中放置目前頁碼。該庫會自動計算目前頁碼和總頁數。您可以使用 TextContainer 物件的 CurrentPageNumberPageCount 方法存取這些值。

Layout API 也提供了一種格式化頁碼的方法。例如,您可以像這樣繪製十六進位頁碼:

text.CurrentPageNumber().Format(p => "0x" + p?.ToString("x2"));

我們的範例庫中包含另一個向 PDF 新增頁首和頁尾的範例。此範例將頁碼格式化為羅馬數字。

插入圖片

俗話說,一圖勝千言。在引用或收據中,您通常會添加公司徽標或其他重要圖片。在本例中,我將使用一張簡潔美觀的圖片。

要使用圖片,您必須先將其新增至文件中。該庫可以從文件或流中載入圖片。目前僅支援柵格格式:PNG、JPEG、JPEG 2000、BMP、GIF 和 TIFF。

取得 Image 物件後,您可以透過呼叫容器的 Image 方法將其設定為一個或多個佈局容器的內容。您可以像操作其他內容一樣,縮放、旋轉、添加內邊距和排列圖片

PdfDocumentBuilder.Create().Generate("image-with-text.pdf", doc =>
{
    var imageFile = new FileInfo("red-flowers-at-butterfly-world.jpg");
    var image = doc.Image(imageFile);

    doc.Pages(pages =>
    {
        pages.Size(PdfPaperSize.A6);
        pages.Content().Column(c =>
        {
            c.Spacing(20);

            c.Item()
                .AlignCenter()
                .Text("Hello, world!")
                .FontSize(20);

            c.Item()
                .AlignCenter()
                .MaxWidth(200)
                .Image(image);
        });
    });
});

範例程式碼在主內容槽中同時使用了文字和圖像。但是,佈局容器只能包含文字或圖像。要將兩者同時包含在頁面的主內容槽中,您需要一個複合容器

我使用 Column 容器將文字和圖像垂直排列,彼此相鄰。 Column 容器的 Item 方法提供了一個子容器。呼叫一次 Item 會建立一個用於文字的容器,再呼叫一次會建立一個用於圖像的容器。包含所有子容器的複合容器就構成了主內容。

要運行範例程式碼,請從我們的範例庫下載花卉圖像並將其放置在您的應用程式的工作目錄中。

線上圖片

如果您只有圖片 URL 而不是文件,請將圖片下載到記憶體流中,然後從該記憶體流建立 Image 物件。以下範例展示如何使用 Layout API 處理線上圖片。

public static async Task AddImageWithTextFromUrl()
{
    using var http = new HttpClient();
    using var stream = await http.GetStreamAsync("url/to/image");

    var memoryStream = new MemoryStream();
    await stream.CopyToAsync(memoryStream);
    memoryStream.Position = 0;

    PdfDocumentBuilder.Create().Generate("online-image-with-text.pdf", doc =>
    {
        var image = doc.Image(memoryStream);

        doc.Pages(pages =>
        {
            pages.Size(PdfPaperSize.A6);
            pages.Content().Column(c =>
            {
                c.Spacing(20);

                c.Item()
                    .AlignCenter()
                    .Text("Hello, world!")
                    .FontSize(20);

                c.Item()
                    .AlignCenter()
                    .MaxWidth(200)
                    .Image(image);
            });
        });
    });
}

由於該方法執行非同步操作(從 URL 下載圖像),因此聲明為 async Task 而不是 void。呼叫者必須使用 await 等待完成,以確保 PDF 產生正確完成。在您自己的程式碼中,類似的方法也可能傳回一個值,在這種情況下,它應該聲明為 async Task<TResult>

創建列表

什麼是列表?您可以將其理解為一組按順序排列的編號項目。佈局 API 沒有提供專門用於清單的容器類型,但使用其他複合容器很容易實現清單功能。

var dayNames = DateTimeFormatInfo.InvariantInfo.DayNames;
var dayNamesSpain = DateTimeFormatInfo.GetInstance(new CultureInfo("es-ES")).DayNames;

PdfDocumentBuilder.Create().Generate("list.pdf", doc => doc.Pages(pages =>
{
    pages.Size(PdfPaperSize.A6);
    pages.Content().Column(column =>
    {
        for (int i = 0; i < dayNames.Length; i++)
        {
            column.Item().Row(row =>
            {
                row.Spacing(5);
                row.AutoItem().Text($"{i + 1}.");
                row.RelativeItem().Text(t =>
                {
                    t.Line(dayNames[i]);
                    t.Line($"In Spain they call it {dayNamesSpain[i]}");
                });
            });
        }
    });
}));

範例程式碼將清單建立為一列行。每行包含兩個項目:第一個項目(左側)包含項目編號,第二個項目(右側)包含項目文字。程式碼明確設定了每行中項目之間的間距。

要排列項目,Row 容器必須明確指定每個項目的大小,或自動計算其大小。在本例中,使用了 AutoItemRelativeItem 方法。因此,行容器會計算第一個項目所需的寬度,然後將剩餘的可用寬度用於第二個項目。

透過使用此方法並根據需要調整行的外觀,您可以建立最適合文件佈局和樣式的清單。

搭建桌子

許多 PDF 文件都包含表格,這不足為奇,因為表格可以提高資料的清晰度和組織性。本節將介紹如何使用 Layout API 在 PDF 中建立表格。

public static void AddTable()
{
    PdfDocumentBuilder.Create().Generate("table.pdf", doc => doc.Pages(pages =>
    {
        pages.Size(PdfPaperSize.A6);

        var color = new PdfGrayColor(75);
        pages.Content().Padding(20).Table(t =>
        {
            t.Columns(c =>
            {
                c.RelativeColumn(4);
                c.RelativeColumn(1);
                c.RelativeColumn(4);
            });

            t.Header(h =>
            {
                h.Cell().Background(color).Text("Month");
                h.Cell().Background(color).Text("Days");
                h.Cell().Background(color).Text("First Day");
            });

            var year = DateTime.Now.Year;
            for (int yearDiff = 0; yearDiff < 4; yearDiff++)
            {
                for (int i = 11; i >= 0; i--)
                {
                    var stats = GetMonthStats(year - yearDiff, i);

                    t.Cell().Text(stats.Item1);
                    t.Cell().Text(stats.Item2);
                    t.Cell().Text(stats.Item3);
                }
            }
        });
    }));
}

private static (string, string, string) GetMonthStats(int year, int monthIndex)
{
    return (
        $"{DateTimeFormatInfo.InvariantInfo.MonthNames[monthIndex]} {year}",
        DateTime.DaysInMonth(year, monthIndex + 1).ToString(),
        new DateTime(year, monthIndex + 1, 1).DayOfWeek.ToString()
    );
}

範例程式碼建立了一個簡單的表格,顯示當前年份和前三年各月的基本資訊。程式碼定義了三列,每列的寬度各不相同。最左側和最右側的列的寬度是中間列的四倍。

程式碼還定義了表格標題,新增了標題儲存格,並為每個儲存格指定了文字和背景顏色。當表格無法完整顯示在一頁上時,標題會在表格所在的每一頁上重複顯示。您可以在範例程式碼產生的 PDF 檔案中看到這種行為。

程式碼使用兩個簡單的循環來建立表格的行。外層循環遍歷年份,內層循環以相反的順序遍歷月份。內層循環獲取每個月份的信息,然後將三個單元格添加到表格中形成一行。

更多詳情,可以閱讀詳細介紹表格容器功能的文章。

PDF 文件支援內部鏈接,允許讀者跳到同一文件內的其他位置。在 PDF 檢視器中,這些連結顯示為可點擊的文字或圖像元素。它們的功能類似於超鏈接,但它們不是指向外部網站,而是在文件內部進行導航。

PDF 內部連結示意圖,顯示了帶有連結和目標圖示的已連接文件部分

許多 PDF 文件使用內部連結作為書籤或目錄,幫助讀者快速跳到不同章節。以下介紹如何使用 Layout API 為文件章節新增連結:

PdfDocumentBuilder.Create().Generate("link.pdf", doc =>
{
    doc.Pages(pages =>
    {
        pages.Content().Column(c =>
        {
            const string SectionName = "Chapter 1";
            c.Item().SectionLink(SectionName).Text("Link");

            c.Item().PageBreak();

            c.Item().Section(SectionName).Text("Target");
        });
    });
});

範例程式碼將第一頁上的文字連結到指定名稱的章節。它透過呼叫包含該文字的佈局容器的 SectionLink 方法來實現這一點。此時,該章節可能尚未存在。在 PDF 檢視器中,該文字將變為可點擊狀態。

然後,程式碼將第二頁上的文字標記為同名章節的開頭。其外觀和行為保持不變,但它成為第一頁連結的目標。這是透過呼叫對應佈局容器的 Section 方法來實現的。

在本例中,連結及其目標均為文字 span 元素,但您可以在任何版面容器上建立章節和連結。它可以是包含映像的容器、表格容器,或是您自己建立的容器。

請參閱我們的範例庫,以了解如何建立 PDF 目錄

設計複雜的PDF佈局

Layout API 提供了多種佈局容器,您可以組合使用這些容器來產生任意複雜的 PDF 文件。您也可以使用自訂元件擴充 API。

本頁的範例刻意簡化,旨在建立簡潔明了的文檔,以便您專注於核心概念,而無需糾結於細節。如果您想了解如何組合不同的容器來產生更複雜的 PDF,請查看我們 GitHub 範例庫中的相應範例。

除了使用內建容器外,您還可以定義和使用自訂佈局元件。當您希望使用單一類別來封裝資料和佈局邏輯時,這些元件尤其有用。將所有內容集中在一個地方,可以使元件更易於理解、修改和重複使用,同時也為您提供了一種靈活的方式來處理複雜的佈局。

若要建立自訂佈局元件,請在您的類別中實作 ILayoutComponent 介面。產生 PDF 時,函式庫會呼叫該介面的 Compose 方法並提供一個 LayoutContext 物件。您的程式碼可以使用此物件建立佈局元素並存取有關正在產生的文件的資訊。

若要為佈局新增自訂佈局元件,請呼叫 LayoutContainer 類別的 Component 方法。在大小和位置方面,自訂元件的行為與文字或圖像完全相同。

有關使用 ILayoutComponent 介面實作自訂元件的範例,請參閱佈局元件範例。

建立 PDF 的其他方法

Docotic.Pdf 提供多種建立 PDF 的方法,每種方法都適用於不同的場景。本節將解釋何時應該使用 Layout API,以及何時其他方法可能更適合您。

何時優先選擇 Layout API

Docotic.Pdf Layout API 是一種強大的工具,可從結構化佈局產生 PDF 檔案。它允許您將文字、圖像、容器和表格組合成任意複雜的嵌套結構來建立文件。生成過程快速、記憶體佔用合理且行為可預測。

Docotic.Pdf 和 Layout 插件構成了一個輕量級、完全獨立的元件。該 API 無需外部程式庫或瀏覽器即可產生 PDF 檔案。這使其成為 .NET 微服務、雲端應用程式(尤其是無伺服器應用程式)以及其他對資源佔用量要求較高的環境的理想選擇。

由於文件佈局是在程式碼中定義的,因此您可以對佈局的任何部分進行單元測試。佈局邏輯可以像其他程式碼一樣重複使用,並且您可以將資料和佈局行為封裝在自訂元件中。

Layout API 的替代方案

一篇專門的文章詳細比較了使用 Docotic.Pdf 建立 PDF 的所有方法。以下是一些最常用的替代方案。

  • HTML 轉 PDF
    重複使用現有的 HTML/CSS 範本。如果您的團隊已經使用 HTML/CSS 產生文檔,並且需要這些文檔的 PDF 版本,請選擇HTML 轉 PDF 方法

  • 底層 PDF 生成
    提供庫中對 PDF 結構和內容的最大控制權。當您需要像素級定位或複雜向量圖形時,請選擇此選項。此方法推薦用於對效能要求極高的場景或需要盡可能小的資源佔用時。

  • 基於模板的 PDF 生成
    提供了一種快速、可預測的方式來填寫文檔,無需設計或排列文檔元素。如果您已有預先定義的 PDF 結構(例如已核准或符合規範的範本),且只需要變更文字欄位、取代佔位符、附加相關文件以及執行類似任務,請選擇此功能。

  • PDF合併與合成
    允許您從現有文件建立 PDF,而不是從頭開始建立。當您需要將圖像、掃描頁面或其他 PDF 文件合併到一個文件中時,請選擇此功能。

與其他 PDF 生成解決方案的比較

本節包含兩個對比表:一個包含關鍵要點,另一個包含詳細的結構化信息,說明帶有 Layout 插件的 Docotic.Pdf 與其他流行的 PDF 生成解決方案的比較情況。

主要對比要點

產生 PDF 檔案有很多不錯的選擇,其中也包括免費工具。但是,諸如簽名、加密或合併文件等功能各不相同,這可能會限制哪些工具真正符合您的需求。

解決方案 何時使用 最適合
使用 Layout 插件的 Docotic.Pdf 當您需要一款高品質、高效能的佈局引擎,能夠產生優化的 PDF 文件,並提供跨平台的高級簽名、加密和 PDF 編輯支援時,這款引擎是您的理想之選 高品質產生發票、報告、報表及類似文檔,並提供卓越的開發體驗。當您需要企業級 PDF 處理和專業支援時,它是您的理想選擇
PDFsharp + MigraDoc 當您需要一個免費的、MIT 許可的 PDF 生成庫,且不需要數位簽章或現代加密演算法時,可以使用此程式庫 在開源或預算受限的專案中建立簡單文檔
QuestPDF 當您需要一個專用於產生 PDF 的現代化排版引擎,而不需要編輯、簽名或加密功能時 提供高品質的 PDF 生成服務,採用 MIT 許可或低成本商業許可,前提是所有非生成功能均由其他方處理
iText 當您需要一款成熟、功能豐富的 PDF 工具包來產生和處理 PDF 文件,並且您準備好以 AGPL/GPLv3 許可證開源您的解決方案,或者購買昂貴的商業許可證時,那麼這款產品可能適合您 已經熟悉 iText API 的團隊,因此不會受到其陡峭學習曲線的影響

詳細比較

請查看表格以了解更廣泛的背景,並形成您自己的結論。

  Docotic.Pdf 與 Layout PDFsharp + MigraDoc QuestPDF iText
PDF功能 功能齊全的PDF庫 PDF 產生和有限編輯 僅產生 PDF 強大的PDF功能
渲染模型 現代的、聲明式的、保留模式的佈局引擎 基於盒子的佈局引擎 現代的、聲明式的、保留模式的佈局引擎 基於盒子的佈局引擎 + 渲染器樹
API 類型 Fluent API 命令式 API Fluent API 命令式 API
開發者體驗 非常棒。 API簡潔、現代且直覺 很好。 API 設計符合傳統規格 非常棒。 API簡潔、現代且直覺 尚可。 API 冗長且過於複雜
字體子集 支援;預設情況下僅嵌入使用的字形 不支援;可能會導致產生的PDF檔案過大 支援;預設情況下僅嵌入使用的字形 支援;預設情況下僅嵌入使用的字形
從右到左(RTL)的內容方向 支援 不支援 支援 支援
數位簽名 支援的,包括 LTV 簽名和外部簽名 不支援 不支援 支援包括 LTV 和外部簽名
加密/權限 完全支持 僅支援RC4加密,不支援AES或證書 不支援 完全支持
外部依賴項 沒有任何 沒有任何 SkiaSharp / 基於 Skia 的組件 沒有任何
支援 為潛在客戶和現有客戶提供專業支援;為持有頂級許可證的客戶提供優先支援 社區支援;專業支援可單獨購買 透過 GitHub 提供社群支持 AGPL 版本獲得社群支援;商業許可持有者獲得專業支持
執照 商業用途,符合條件的用例可獲得免費許可 MIT MIT適用於個人和小型公司;大型企業需要商業許可證 AGPL 適用於開源項目,而專有項目則使用昂貴的商業許可
開發者授權 擁有所有授權的無限開發者 擁有所有授權的無限開發者 MIT 授權下開發者人數不限;專業版授權下開發者人數為 10 人;企業版授權下開發者人數不限 AGPL 版本允許無限數量的開發者;商業許可則按開發者數量授權

結論

Docotic.Pdf 及其 Layout 外掛程式提供了一種現代化、高效能、高品質的 C# 和 VB.NET PDF 產生方式。該庫可產生報告、報表、發票及類似文件。其精心設計、流暢易用的 API 為開發者提供了卓越的體驗。您可以信賴 Bit Miracle 為 Docotic.Pdf 及其外掛程式提供的專業支援。

與其他一些 PDF 生成解決方案不同,Docotic.Pdf 是一個功能齊全的 PDF API。該庫可以使用數位簽章(包括 LTV 簽章)對產生的 PDF 進行簽署。 Docotic.Pdf 能夠使用儲存在 USB 令牌和智慧卡等安全硬體上的憑證。此外,它還支援基於雲端的硬體安全模組 (HSM),例如 Microsoft Azure Key Vault 和 AWS Key Management Service (KMS)。

使用 Docotic.Pdf,您可以將電子表格或語音備註等輔助文件附加到產生的 PDF 中。要在網頁或類似介面上顯示文檔,您可以從文檔的一個或多個頁面建立縮圖

後續步驟: