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

在 C# 和 VB.NET 中將 HTML 轉換為 PDF

如果您已經投入大量時間與金錢來建立 HTML 格式的內容,您可能會想從該 HTML 建立 PDF。對於想避免重複工作的人來說,這種方法是自然的選擇。

本文是使用 Docotic.Pdf 及其免費的 HtmlToPdf 增益集將 HTML 轉換為 PDF 的詳細指南。

如需了解為何 Docotic.Pdf 是正確的選擇、如何安裝增益集,以及轉換在內部如何運作,請參閱 HTML to PDF API 概覽 頁面。

HTML 轉 PDF 轉換

簡單的 HTML 轉 PDF C# 轉換

首先,安裝增益集。

Install-Package BitMiracle.Docotic.Pdf.HtmlToPdf

使用 HTML to PDF API,C# 轉換程式碼可以如下所示:

static async Task ConvertUrlToPdfAsync(string urlString, string pdfFileName)
{
    using var converter = await HtmlConverter.CreateAsync();
    using var pdf = await converter.CreatePdfAsync(new Uri(urlString));
    pdf.Save(pdfFileName);
}

這相當簡單。只需要兩次呼叫即可產生 PDF 文件。

此程式碼建立轉換器的執行個體,並使用它從 HTML 產生 PDF。您可以 編輯 PDF 文件,或使用 數位簽章 進行簽署。為了簡化起見,範例程式碼會將文件按原樣儲存。

如您所見,API 是非同步的,根本不提供同步方法。

在同步程式碼中使用非同步 API

有些情況下,您需要從同步程式碼呼叫 API。例如,當您的主控台應用程式使用較舊版本的 C#,且沒有 async Main 時。不用擔心,您仍然可以在應用程式中使用此增益集。

以下程式碼示範如何在一般同步方法中將 URL 轉換為 PDF:

Task.Run(async () =>
{
    using var converter = await HtmlConverter.CreateAsync();
    var uri = new Uri("https://bitmiracle.com/pdf-library/html-pdf/");
    using var pdf = await converter.CreatePdfAsync(uri);
    pdf.Save("output.pdf");
}).GetAwaiter().GetResult();

VB.NET 應用程式使用類似的程式碼。以下片段示範如何在同步的 VB.NET 程式碼中將 HTML 轉換為 PDF。

Task.Run(
    Async Function()
        Using converter = Await HtmlConverter.CreateAsync()
            Dim uri = New Uri("https://bitmiracle.com/pdf-library/html-pdf/")
            Using pdf = Await converter.CreatePdfAsync(uri)
                pdf.Save("output.pdf")
            End Using
        End Using
    End Function
).GetAwaiter().GetResult()

請注意,一般不建議以同步方式呼叫非同步方法,因此僅在別無選擇時才使用此包裝器。

範例程式碼

我們提供主控台、Windows Forms 與 WPF 應用程式的範例程式碼。可從我們的 GitHub 儲存庫下載完整測試專案:

另外還有一組 HTML to PDF 範例。每個範例都有 C# 和 VB.NET 版本。

使用 HTML 字串或檔案建立 PDF:

使用 API 將 HTML 字串轉換為 PDF 很簡單。字串可以包含完整的 HTML 文件,或只是一個片段。轉換器會為您從 HTML 程式碼建立 PDF。

using var converter = await HtmlConverter.CreateAsync();

var html = "<body><br><br><br><h1>Hello, World</h1></body>";
using var pdf = await converter.CreatePdfFromStringAsync(html);
pdf.Save("output.pdf");

HTML 可以包含對圖片、腳本和 CSS 檔案的相對參照。若要正確轉換這類程式碼,您需要為 HTML 中所有相對連結指定基底 URL。以下示範如何使用轉換選項指定基底 URL:

using var converter = await HtmlConverter.CreateAsync();

var incompleteHtml = "<img src=\"/images/team.svg\"></img>";

var options = new HtmlConversionOptions();
options.Load.BaseUri = new Uri("https://bitmiracle.com/");

using var pdf = await converter.CreatePdfFromStringAsync(incompleteHtml, options);
pdf.Save("output.pdf");

我們的 GitHub 儲存庫包含 完整測試專案

轉換 HTML 檔案幾乎與轉換 URL 相同。只要使用接受路徑而非 URL 的 CreatePdfAsync 多載即可。將 HTML 檔案轉換為 PDF 時,C# 或 VB.NET 程式碼也支援基底 URL 與其他選項。

var sampleHtmlPath = @"C:\path\to\sample.html";
using var pdf = await converter.CreatePdfAsync(sampleHtmlPath);
pdf.Save("output.pdf");

您也可以使用 API 將 SVG 圖片轉換為 PDF

使用自訂頁面大小、邊距與縮放

處理版面較寬的網頁時,您可以增加輸出 PDF 的大小,或將內容縮小以符合 PDF 頁面。為了更好地定位縮放後的內容,您也可以設定邊距。

良好縮放的 PDF 可提供更好的閱讀體驗,因為讀者不需要放大或縮小即可正確檢視內容。如果 HTML 文件因字型太小而難以閱讀,您可以將內容放大。

預設情況下,API 產生的 PDF 頁面大小等同於 A4。沒有邊距,也沒有放大。使用轉換選項,您可以變更這些設定。

了解在從 HTML 產生 PDF 時如何設定縮放係數與邊距

using var converter = await HtmlConverter.CreateAsync();

var html = "<html><head><style>body { background-color: coral; margin-top: 100px;}</style></head>" +
"<body><h1>Did you notice the margins and the scale?</h1></body></html>";

var options = new HtmlConversionOptions();
options.Page.MarginLeft = 10;
options.Page.MarginTop = 20;
options.Page.MarginRight = 30;
options.Page.MarginBottom = 40;
options.Page.Scale = 1.5;

using var pdf = await converter.CreatePdfFromStringAsync(html, options);
pdf.Save("output.pdf");

Docotic.Pdf 範例儲存庫包含 完整專案

HTML to PDF API 可以在產生的頁面上加入可重複的頁尾/頁首區塊。轉換器會依據 頁面選項 中指定的 HTML 樣板建立這些區塊。我們建議在樣板內對圖片使用內嵌樣式與 Data URI。

轉換器會將頁首與頁尾放置在頁面邊距內。由於預設頁面邊距很小,頁首與頁尾的內容可能不會顯示。我們建議明確指定上邊距與下邊距。其大小應分別與頁首及頁尾的大小相符。

了解如何變更 HTML to PDF 並加入頁首與頁尾

using var converter = await HtmlConverter.CreateAsync();

var options = new HtmlConversionOptions();
options.Page.HeaderTemplate = File.ReadAllText("header-template.html");
options.Page.MarginTop = 50;

options.Page.FooterTemplate = File.ReadAllText("footer-template.html");
options.Page.MarginBottom = 50;

var url = new Uri("https://www.iana.org/numbers");
using var pdf = await converter.CreatePdfAsync(url, options);
pdf.Save("output.pdf");

這些樣板使用一般 HTML 程式碼,並支援少數變數。這些變數是 datetitleurlpageNumbertotalPages頁首樣板頁尾樣板 皆支援相同的一組變數。

完整的 測試專案與樣板程式碼 位於 Docotic.Pdf 範例儲存庫中。範例程式碼示範如何在樣板中使用這些變數與 Data URI。

密碼保護的 HTML 轉 PDF C# 轉換

有些網頁需要驗證才能存取。當您存取需要 HTTP 驗證的安全 URL 時,瀏覽器會要求您提供使用者名稱與密碼。

使用 轉換選項,您可以告訴 API 為需要登入的網頁提供認證資訊。

以下 C# 程式碼示範如何將受密碼保護的 HTML 轉換為 PDF

using var converter = await HtmlConverter.CreateAsync();
var url = new Uri("http://httpbin.org/basic-auth/foo/bar");

var options = new HtmlConversionOptions();
options.Authentication.SetCredentials("foo", "bar");

using var pdf = await converter.CreatePdfAsync(url, options);
pdf.Save("output.pdf");

在範例儲存庫中找 完整可運作的範例

如果頁面需要設定某些 Cookie 才能正常運作,也同樣很容易。只要將這些 Cookie 加入選項即可。如下所示:

var options = new HtmlConversionOptions();
options.Cookies.Add(new Cookie("sessionID", "my-session-ID"));

using var pdf = await converter.CreatePdfAsync(url, options);
pdf.Save("output.pdf");

延遲開始轉換

預設情況下,轉換會在載入後立即開始。若頁面在載入後仍會持續更新一段時間,延遲 HTML 轉 PDF 轉換會很有用。這在處理由 JavaScript 或 AJAX 呼叫產生的動態內容時很常見。

Acid 3 測試就是一個非常適合在轉換前加入延遲的頁面範例。此測試會執行多項檢查,以評估瀏覽器正確呈現複雜網頁的能力。這些檢查需要時間。請嘗試變更下列程式碼中的等待時間,以查看它如何影響轉換結果。

var options = new HtmlConversionOptions();
options.Start.SetStartAfterDelay(10 * 1000);

using var converter = await HtmlConverter.CreateAsync();
var url = new Uri("http://acid3.acidtests.org/");
using var pdf = await converter.CreatePdfAsync(url, options);
pdf.Save("output.pdf");

上述程式碼示範如何以延遲方式將 HTML 轉換為 PDF。雖然額外時間有助於取得更好的結果,但請注意,加入延遲可能會影響效能。延遲不足會對轉換品質產生負面影響。另一種替代延遲的方法是 使用腳本,讓腳本持續執行直到頁面就緒。

您可以在 Docotic.Pdf 範例儲存庫中取得 完整測試專案

在轉換前執行 JavaScript

此增益集 API 提供在轉換前執行 JS 程式碼的方法。程式碼可以動態產生或修改 HTML 內容。例如,它可以切換元素,或使動態內容載入發生。

以下程式碼示範如何在 JavaScript 完成之前延遲 HTML 轉 PDF 轉換。

using var converter = await HtmlConverter.CreateAsync();

var options = new HtmlConversionOptions();
var js = @"document.body.style.backgroundColor = 'green';";
options.Start.SetStartAfterScriptRun(js);

var url = new Uri("https://google.com");
using var pdf = await converter.CreatePdfAsync(url, options);
pdf.Save("output.pdf");

上述片段只使用非常簡單的程式碼來說明此做法。若要看更貼近實際情境的範例,請查看我們 GitHub 儲存庫中的 對應範例應用程式。該應用程式示範如何處理動態載入內容的頁面。應用程式中的 JavaScript 程式碼會捲動頁面,直到不再有新內容為止。之後便會進行 PDF 轉換。

在 .NET 中將 HTML 轉換為 PDF 並忽略 SSL 錯誤

在發出安全請求以載入 HTML 時,增益集會檢查用於驗證網站身分並啟用加密連線的 SSL 憑證是否有效且受信任。

預設情況下,若 HTML 轉 PDF 轉換器基於任何原因不信任該憑證,增益集會擲出例外。這通常是因為自簽憑證、已撤銷憑證或已過期憑證所致。

如果您了解接受不受信任憑證的風險,可以透過 引擎選項 告訴增益集略過檢查。

var engineOptions = new HtmlEngineOptions
{
    IgnoreSslErrors = true
};
using var converter = await HtmlConverter.CreateAsync(engineOptions);

var url = new Uri("https://self-signed.badssl.com/");
using var pdf = await converter.CreatePdfAsync(url);
pdf.Save("output.pdf");

如需 完整程式碼,請前往 Docotic.Pdf 範例儲存庫。

將 HTML 疊加到現有 PDF 上

有些情況下,您可能希望使用現有 PDF 作為轉換結果的背景。例如,當您有一張表單圖片,並想在圖片的空白區域上放些內容。結果會看起來像是填妥的表單。使用 Docotic.Pdf 和此增益集即可達成。

此流程涉及先從 HTML(疊加內容)建立新的 PDF,然後將其與現有 PDF 合併。最終文件會同時包含原始內容與新的疊加層。以下程式碼示範此流程。

using var converter = await HtmlConverter.CreateAsync();

var options = new HtmlConversionOptions();
options.Page.SetSizeInches(4.13, 5.83);

string htmlCode =
    "<div style=\"position: absolute; top: 270px; right: 100px;\">" +
    "I would like to put this here</div>";
using var htmlPdf = await converter.CreatePdfFromStringAsync(htmlCode, options);

using var pdf = new PdfDocument("pdf-to-merge-with.pdf");
var xObj = pdf.CreateXObject(htmlPdf.Pages[0]);

pdf.Pages[0].Canvas.DrawXObject(xObj, 0, 0);
pdf.Save("output.pdf");

為疊加層指定頁面大小很重要。通常,該大小應與您要疊加的頁面大小相同。接著您需要產生包含疊加內容的新 PDF。請注意,背景預設是透明的。如有需要,您可以透過 在轉換前執行腳本 來變更背景。

上面的程式碼:

  • 從 HTML 建立一個具有透明頁面的 PDF 文件
  • 開啟現有 PDF
  • 在現有文件中,從轉換文件的第一頁建立一個 XObject
  • 在現有文件的第一個 PDF 頁面上繪製該 XObject

完整的 含範例來源 PDF 的測試專案 位於 Docotic.Pdf 範例儲存庫中。