跳至頁尾內容
使用IRONPDF

以 C# 實作管理儀錶板的一鍵匯出 PDF 功能

大規模保留HTML內容的問題

IronPDF首頁 當一個組織退役一個舊有的CMS系統、內聯網或是面向公眾的入口網站時,其上的內容不會簡單地不再重要。 一個醫院退役病人健康文章資料庫,仍然需要保存這些文章;一個政府部門重新設計其網站,必須保留某一特定時間點存在的公告;一個律師事務所關閉案例研究平台,需要將每頁轉換成在法律保留訴訟中有效的格式。

規模是每一種手動方法都會失敗的地方。 基於瀏覽器的列印至PDF功能對於一個文件很有用。 它不是1萬個文件的解決方案。無頭瀏覽器的腳本化工作,直到您遇到格式錯誤的HTML,丟失的資產或身份驗證牆,而遺留內容很少是乾淨的。

現有的批量轉換工具在舊有標記上有類似問題:來自2005年的內嵌樣式,非標準的表格佈局,引用至不再解析的路徑的圖像。 它們要麼默默失敗,要麼生成布局錯亂的PDF,或者需要每頁手動修復。 同時,IT團隊無法證明將遺留基礎結構無限期線上運行只是為了支持本應在幾個月前完成的遷移。

輸出也需要一致。 無論是醫院存檔健康文章、金融機構保存披露頁面以符合監管要求,或是律師事務所建立保留存檔,所有人都需要生成的PDF看起來像是來自同一系統,而不是瀏覽器一個個單獨導出的集合。 在本教程中,我們將引導您通過IronPDF範例,了解這個程式庫如何提升您的專案工作流程。

解決方案:使用IronPDF自動將HTML批量轉換為PDF

Iron Software的IronPDF讓.NET應用程式可以批量轉換HTML文件,HTML字串,或者線上URL為標準化PDF,在一次自動化運行中完成。 遷移腳本從源頭讀取:一個HTML文件目錄、HTML塊的資料庫或在舊伺服器下線之前要捕捉的URL清單,然後將每頁輸入至ChromePdfRenderer,並將輸出寫入到存檔目的地。

基於Chromium的渲染引擎處理不一致的標記、內嵌樣式和嵌入資產,像瀏覽器那樣生產視覺上忠實的快照,不論原始的HTML如何編寫。 沒有需要維護的瀏覽器自動化黑客,沒有讓50000頁存檔貴不可應的每文件API成本。轉換工作在.NET控制台應用程式或背景服務中運行,一個NuGet套件,無外部進程。

實際操作方式:C# PDF文件建立

1. 遷移腳本枚舉源內容

該腳本通常是為了遷移而構建的控制台應用程式,可一次性執行或用於增量內容集的可重複性任務。 它開始於枚舉源:磁碟上的.html文件目錄、帶有HTML塊和元資料(原始URL、建立日期、內容ID)的資料表,或在舊伺服器下線之前要捕捉的實時網頁平面列表。

對於資料庫源,查詢返回HTML內容和將填充存檔清單的元資料。對於URL列表,處理順序可根據優先順序排序,高流量頁面或法律敏感內容優先捕獲。

2. 樣式表注入標準化輸出

遺留的HTML本質上是不一致的。 同一CMS系統不同時期的頁面可能具有不同的基礎字體大小、邊距約定和佈局假設。 在渲染之前,腳本可以選擇性地在每個HTML字串前加上一個標準化的<style>塊——設置統一的邊距、一致的正文字體和固定的頁面寬度——以便每個存檔的PDF文件共享相同的視覺基礎,無論原始樣式如何。

這一標準化步驟區別於乍看之下是統一文件集合的存檔和看似隨機的瀏覽器捕捉集。

3. ChromePdfRenderer將每頁轉換為PDF文件

對於磁碟上的HTML文件或資料庫中的HTML字串,RenderHtmlAsPdf()負責轉換。 BaseUrlPath參數在原始文件的目錄中解析相對的圖像和樣式表引用,保留嵌入的資產:

using IronPdf;

var renderer = new ChromePdfRenderer();

renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.A4;

renderer.RenderingOptions.MarginTop = 20;

renderer.RenderingOptions.MarginBottom = 20;

string sourceDir = @"C:\LegacyContent\html";

string archiveDir = @"C:\Archive\pdf";

Directory.CreateDirectory(archiveDir);

foreach (string htmlFile in Directory.EnumerateFiles(sourceDir, "*.html"))
{
    string html = File.ReadAllText(htmlFile);
    PdfDocument pdf = renderer.RenderHtmlAsPdf(html, sourceDir);
    string outputPath = Path.Combine(archiveDir,
        Path.GetFileNameWithoutExtension(htmlFile) + ".pdf");

    pdf.SaveAs(outputPath);
    Console.WriteLine($"Archived: {outputPath}");
}
using IronPdf;

var renderer = new ChromePdfRenderer();

renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.A4;

renderer.RenderingOptions.MarginTop = 20;

renderer.RenderingOptions.MarginBottom = 20;

string sourceDir = @"C:\LegacyContent\html";

string archiveDir = @"C:\Archive\pdf";

Directory.CreateDirectory(archiveDir);

foreach (string htmlFile in Directory.EnumerateFiles(sourceDir, "*.html"))
{
    string html = File.ReadAllText(htmlFile);
    PdfDocument pdf = renderer.RenderHtmlAsPdf(html, sourceDir);
    string outputPath = Path.Combine(archiveDir,
        Path.GetFileNameWithoutExtension(htmlFile) + ".pdf");

    pdf.SaveAs(outputPath);
    Console.WriteLine($"Archived: {outputPath}");
}
Imports IronPdf
Imports System.IO

Dim renderer As New ChromePdfRenderer()

renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.A4

renderer.RenderingOptions.MarginTop = 20

renderer.RenderingOptions.MarginBottom = 20

Dim sourceDir As String = "C:\LegacyContent\html"

Dim archiveDir As String = "C:\Archive\pdf"

Directory.CreateDirectory(archiveDir)

For Each htmlFile As String In Directory.EnumerateFiles(sourceDir, "*.html")
    Dim html As String = File.ReadAllText(htmlFile)
    Dim pdf As PdfDocument = renderer.RenderHtmlAsPdf(html, sourceDir)
    Dim outputPath As String = Path.Combine(archiveDir, Path.GetFileNameWithoutExtension(htmlFile) & ".pdf")

    pdf.SaveAs(outputPath)
    Console.WriteLine($"Archived: {outputPath}")
Next
$vbLabelText   $csharpLabel

HTML文件轉換為PDF格式

輸出文件

範例輸出:HTML文件與輸出PDF

IronPDF範例輸出 對於需要從運行中的伺服器捕捉的活URL,RenderUrlAsPdf()處理每個請求。並行批處理保持運行時間在大URL集中的可管理範圍內:

using IronPdf;

var renderer = new ChromePdfRenderer();

int completed = 0, failed = 0;

await Parallel.ForEachAsync(urlList,
    new ParallelOptions { MaxDegreeOfParallelism = 4 },
    async (url, _) =>
    {
        try
        {
            PdfDocument pdf = renderer.RenderUrlAsPdf(url);
            string filename = Uri.EscapeDataString(url).Replace("%", "_") + ".pdf";
            pdf.SaveAs(Path.Combine(@"C:\Archive\pdf", filename));
            Interlocked.Increment(ref completed);
        }
        catch (Exception ex)
        {
            Interlocked.Increment(ref failed);
            Console.Error.WriteLine($"Failed: {url} — {ex.Message}");
        }
        Console.WriteLine($"Progress: {completed} completed, {failed} failed");
    });
using IronPdf;

var renderer = new ChromePdfRenderer();

int completed = 0, failed = 0;

await Parallel.ForEachAsync(urlList,
    new ParallelOptions { MaxDegreeOfParallelism = 4 },
    async (url, _) =>
    {
        try
        {
            PdfDocument pdf = renderer.RenderUrlAsPdf(url);
            string filename = Uri.EscapeDataString(url).Replace("%", "_") + ".pdf";
            pdf.SaveAs(Path.Combine(@"C:\Archive\pdf", filename));
            Interlocked.Increment(ref completed);
        }
        catch (Exception ex)
        {
            Interlocked.Increment(ref failed);
            Console.Error.WriteLine($"Failed: {url} — {ex.Message}");
        }
        Console.WriteLine($"Progress: {completed} completed, {failed} failed");
    });
Imports IronPdf
Imports System.IO
Imports System.Threading
Imports System.Threading.Tasks

Dim renderer As New ChromePdfRenderer()

Dim completed As Integer = 0
Dim failed As Integer = 0

Await Parallel.ForEachAsync(urlList,
    New ParallelOptions With {.MaxDegreeOfParallelism = 4},
    Async Function(url, _) As Task
        Try
            Dim pdf As PdfDocument = renderer.RenderUrlAsPdf(url)
            Dim filename As String = Uri.EscapeDataString(url).Replace("%", "_") & ".pdf"
            pdf.SaveAs(Path.Combine("C:\Archive\pdf", filename))
            Interlocked.Increment(completed)
        Catch ex As Exception
            Interlocked.Increment(failed)
            Console.Error.WriteLine($"Failed: {url} — {ex.Message}")
        End Try
        Console.WriteLine($"Progress: {completed} completed, {failed} failed")
    End Function)
$vbLabelText   $csharpLabel

從URL生成的文件

從URL生成的文件

範例輸出

URL轉PDF範例輸出 每個輸出PDF被保存到一個鏡像原始站點層級的文件夾結構中,並具有錄製的原始URL、轉換時間戳和每個處理文件的輸出路徑的清單文件。

真實世界的好處

吞吐量。 IronPDF在毫秒內渲染每一頁。 一個包含四個並行執行緒的10,000頁存檔通常在幾小時內完成,在標準的伺服器硬體上,沒有夜間批量窗口,沒有轉換運行之間的手動交接。

視覺保真度。 基於Chromium的渲染意味著表格、CSS布局、嵌入圖像和內嵌樣式按與瀏覽器相同的方式處理。 存檔的PDF匹配原始頁面的外觀,而不是精簡的近似。

按計劃退役。 一旦存檔運行完成並驗證了清單,遺留的伺服器、資料庫和CMS安裝可以使得關閉。 內容存在作為一個永久、自給自足的PDF集合,這取決於沒有什麼是舊基礎設施提供的。

監管合規性。 不可變的PDF快照滿足法律保存和保留要求。 IronPDF支持PDF/A輸出以進行長期存檔保存,一個單一的渲染選項將輸出轉換為ISO標準格式並被接受以進行正規文件保留。

內容品質的一致性。 在渲染之前注入標準化樣式表可確保每個存檔的PDF共享統一的邊距、字體和頁面尺寸,無論原始的HTML是由遵循標準的開發人員編寫的還是由從Word中粘貼的內容作者製作的。

無每文件成本。 轉換是在流程中運行的。 沒有對外部轉換供應商的API調用,也沒有使大存檔比例過高的定價模式。無論是轉換500頁,還是50000頁,在基礎設施層面成本相同。

結論

一個有著退役期限的內容遷移不留下時間給手動轉換工作流或對於繁瑣HTML的失效工具。 轉換需要自動運行,產生批量的一致輸出,並在舊伺服器下線之前完成。

由IronPDF提供支持的.NET遷移腳本涵蓋整個表面,枚舉源內容,標準化樣式,通過Chromium渲染每頁,寫入存檔目的地,並記錄失敗以供審查。 IronPDF在ironpdf.com上用C#處理PDF生成的全生命周期,從渲染HTML字串和URL到保存、流媒體和操作文件。 如果您正在規劃遷移或開始試點運行,免費30天試用為您提供足夠時間以轉換您遺留內容的代表性樣本,並在提交完整存檔之前驗證輸出。

Curtis Chau
技術作家

Curtis Chau擁有Carleton大學的電腦科學學士學位,專精於前端開發,擁有Node.js、TypeScript、JavaScript和React的專業知識。Curtis熱衷於建立直觀且美觀的使用者介面,喜愛使用現代框架並建立結構良好、視覺吸引力的手冊。

除了開發,Curtis對物聯網(IoT)有濃厚的興趣,探索創新的方法來整合硬體和軟體。在空閒時間,他喜歡玩遊戲和建立Discord機器人,結合他對技術的熱愛與創造力。

Iron 支援團隊

我們線上24小時,每週5天。
聊天
電子郵件
給我打電話