如何在 C# 中實現符合 PDF/A 標準的 PDF 歸檔

This article was translated from English: Does it need improvement?
Translated
View the article in English

IronPDF為 .NET 開發人員提供了一條直接建立、轉換和驗證符合ISO 19005標準的歸檔 PDF**的途徑,從而確保文件在任何系統上都能以相同的方式呈現,無論現在還是幾十年後。 從將HTML 渲染為 PDF/A並將現有文件轉換為PDF/A-1bPDF/A-2bPDF/A-3b ,到嵌入來源資料以符合ZUGFeRDFactur-X 電子發票規範,IronPDF 可處理完整的PDF/A 轉換**工作流程,而無需離開 .NET 生態系統。

TL;DR:快速入門指南

本教學涵蓋了在 C# 中建立、轉換和驗證符合 PDF/A 標準的文件——包括電子發票格式和現實世界的政府存檔要求。

-適用對象:使用.NET 建立應用程式的開發人員,這些應用程式會產生用於長期儲存或受監管歸檔的文件——政府記錄管理、法律文件、財務審計追蹤、醫療保健記錄保留或電子發票平台,其中 PDF/A 是硬性合規要求。 -你將建立的內容:從零開始建立 HTML 到 PDF/A 的渲染,將現有 PDF 轉換為 PDF/A-1b/2b/3b,為 ZUGFeRD/Factur-X 電子發票嵌入來源資料附件,進行 PDF/A 合規性驗證並報告失敗情況,以及符合 NARA、法院和醫療記錄要求的實際歸檔模式。 -運行環境:任何 .NET 環境 — .NET 10、.NET 8 LTS、.NET Framework 4.6.2+、.NET Standard 2.0。 PDF/A 轉換和驗證完全在本地運行; 生成過程中不需要外部驗證工具。 -何時使用此方法:當您的應用程式產生必須長期保存的文件時——發票、合約、合規報告、法庭文件或醫療記錄——並且監管要求(NARA、歐盟存檔標準、HIPAA、SEC)要求採用獨立、可驗證的 PDF/A 格式。 -技術上的重要性:標準 PDF 檔案可以引用外部字體、嵌入活動內容,並依賴系統特定的渲染方式——所有這些都會隨著時間的推移而失效。 PDF/A 從格式層面禁止了這些依賴關係,將渲染所需的一切都直接嵌入到文件中,從而保證在任何相容的檢視器上都能獲得完全相同的輸出結果。

只需幾行程式碼即可將現有 PDF 檔案轉換為 PDF/A 格式:

Nuget Icon立即開始使用 NuGet 建立 PDF 檔案:

  1. 使用 NuGet 套件管理器安裝 IronPDF

    PM > Install-Package IronPdf

  2. 複製並運行這段程式碼。

    using IronPdf;
    
    PdfDocument pdf = PdfDocument.FromFile("report.pdf");
    pdf.SaveAsPdfA("archived-report.pdf", PdfAVersions.PdfA3b);
  3. 部署到您的生產環境進行測試

    立即開始在您的專案中使用 IronPDF,免費試用!
    arrow pointer

購買或註冊 IronPDF 的 30 天試用版後,請在應用程式開始時新增您的授權金鑰。

IronPdf.License.LicenseKey = "KEY";
IronPdf.License.LicenseKey = "KEY";
Imports IronPdf

IronPdf.License.LicenseKey = "KEY"
$vbLabelText   $csharpLabel

!{--010011000100100101000010010100100100000101010010010110010101111101001110010101010101010101010101010101010101010 0100010111110100100101001101010100010000010100110001001100010111110100001001001100010011110010101010

as-heading:2(目錄)

-理解 PDF/A -什麼是 PDF/A?它為什麼重要? PDF/A 版本詳解


什麼是PDF/A?它為什麼重要?

PDF/A 是 PDF 格式 (ISO 19005) 的一個 ISO 標準化子集,專門用於電子文件的長期、可靠存檔。 與可以引用外部字體、連結到外部內容並依賴系統特定渲染行為的標準 PDF 不同,PDF/A 文件是完全獨立的。 渲染文件所需的所有字體、顏色設定檔和元資料都直接嵌入到文件中。

這很重要,因為無論作業系統或軟體版本如何,PDF/A 文件無論是在今天打開還是在 100 年後打開,在任何相容的檢視器上,其呈現效果都將完全相同。 它不依賴可能消失的外部資源,不依賴已安裝的特定字體,並且在顏色或透明度的顯示方式上不存在歧義。

除了技術上的可靠性之外,PDF/A 合規性通常是一項硬性要求,而不僅僅是最佳實踐。強制要求 PDF/A 的行業和機構包括:

法律和司法系統—美國、歐盟和許多其他司法管轄區的法院要求或強烈建議使用 PDF/A 格式進行電子歸檔。 美國聯邦法院系統的 CM/ECF 文件歸檔標準將 PDF/A 作為長期記錄保存的首選格式。

政府機構-美國國家檔案館和記錄管理局 (NARA) 指定 PDF/A 為傳輸永久電子記錄的可接受格式。 同樣,歐盟委員會也強制要求某些官方出版物和監管文件採用 PDF/A 格式。

金融服務和審計-美國證券交易委員會等監管機構接受 PDF/A 文件,內部稽核團隊也經常採用 PDF/A 文件,以確保財務報表、報告和支援文件能夠長期保持不可更改和可驗證的狀態。

醫療保健-醫療記錄保存規定(例如美國的 HIPAA)沒有強制規定特定的文件格式,但 PDF/A 已成為存檔患者記錄、影像報告和臨床文件的事實標準,因為它保證了長期可讀性。

簡而言之,當文件必須在時間、系統和組織邊界之間保持不變時,您可以使用 PDF/A 格式。 如果您的應用程式產生的文件可能會在幾年後被引用——發票、合約、合規報告、醫療記錄——PDF/A 是正確的選擇。


PDF/A 版本詳解

PDF/A 標準經歷了多個版本的發展,每個版本都在前一個版本的基礎上進行改進,以支援更多的 PDF 功能,同時保持嚴格的存檔保證。 了解不同版本之間的差異對於選擇適合您使用場景的版本至關重要。

PDF/A-1(基本存檔)

PDF/A-1 (ISO 19005-1:2005) 是該標準的第一個版本,基於 PDF 1.4。它確立了核心存檔要求:所有字體都必須嵌入; 禁止加密; 不允許上傳音訊/視訊內容; 禁止使用 JavaScript。 PDF/A-1 分為兩個符合性等級:

PDF/A-1b基本):確保文件的可靠視覺再現。 這是最低合規級別,保證文件渲染後看起來正確。

PDF/A-1a可存取):在1b的基礎上增加了結構和語義要求,包括用於輔助功能的標記內容、Unicode 字元映射和邏輯閱讀順序。 這是更高的標準,也是在無障礙合規性至關重要時所必須達到的標準。

PDF/A-1 是應用最廣泛的版本,至今仍被廣泛使用,尤其是在法律和政府領域,在這些領域,廣泛的兼容性比新功能更為重要。

PDF/A-2(JPEG2000,透明度)

PDF/A-2 (ISO 19005-2:2011) 基於 PDF 1.7,並引入了對 PDF/A-1 中不存在的功能的支援:

JPEG2000 影像壓縮:與 PDF/A-1 中提供的 JPEG 壓縮相比,它提供了更好的品質大小比。

透明度和圖層支援:無需將所有內容扁平化為不透明元素,即可實現更複雜的視覺佈局。

嵌入式 PDF/A 附件: PDF/A-2 文件可以將其他符合 PDF/A 標準的文件作為附件嵌入(但只能是 PDF/A 文件,不能是任意格式)。

PDF/A-2 包含與 PDF/A-1 ( 2b2a ) 相同的符合性級別,以及一個新的級別: PDF/A-2u ( Unicode ),它要求所有文本都進行 Unicode 映射,但不需要級別a的完整結構標記。

PDF/A-3(嵌入式文件)

PDF/A-3 (ISO 19005-3:2012) 是現代工作流程中最重要的擴充。 它與 PDF/A-2 (PDF 1.7) 共享相同的基礎,並保留了其所有功能,但增加了一項關鍵功能:能夠在 PDF/A 文件中嵌入任何格式的文件

這表示您可以將原始 XML 來源資料、CSV 匯出檔案、電子表格或任何其他機器可讀檔案與人可讀的視覺文件一起附加。 PDF/A-3 容器成為一個包含表示層和底層資料的單一軟體包。

這項功能是現代電子發票標準的基礎:

ZUGFeRD:原籍德國,現在已被歐盟採用,稱為Factur-X 。 將結構化的 XML 發票資料(跨行業發票格式)嵌入 PDF/A-3 文件中,該文件同時包含可視化的、易於閱讀的發票。單一文件即可滿足人工和機器處理的需求。

PDF/A-3 符合性等級遵循相同的模式: 3b (視覺)、 3a (可存取 + 帶標籤)和3u (Unicode 映射)。

PDF/A-4(基於 PDF 2.0)

PDF/A-4 (ISO 19005-4:2020) 是基於 PDF 2.0 的最新版本。它簡化了符合性層級結構; 不再有a/b/u差別。 相反,PDF/A-4 定義了三種規格:

PDF/A-4:通用存檔的基本規格。

PDF/A-4f:允許嵌入任何格式的文件(類似 PDF/A-3)。

PDF/A-4e:專為工程文件設計; 支援 3D 內容、富媒體和其他技術元素。

PDF/A-4 也受益於 PDF 2.0 本身的改進,包括改進的標記結構和使用XMP (可擴展元資料平台)增強的元資料功能。

PDF/A-4 的採用率正在提高,但與 PDF/A-2 和 PDF/A-3 相比,它仍然沒有得到檢視器和驗證器的普遍支援。

你應該使用哪個版本?

選擇合適的PDF/A版本取決於您的特定需求:

決策流程圖展示了根據嵌入文件、JPEG2000、透明度和相容性等要求選擇 PDF/A 版本的路徑

最大相容性:對於現有的系統、驗證器和檢視器(尤其是在法律和政府環境中),請使用PDF/A-1bPDF/A-2b

電子發票:對於需要嵌入式來源資料的 ZUGFeRD、Factur-X 或類似標準,請使用PDF/A-3b

無障礙合規性:對於第 508 節或 WCAG 要求,請選擇您正在使用的任何版本的a規等級( PDF/A-1aPDF/A-2aPDF/A-3a )。

現代工作流程:對於支援 PDF 2.0 的最新功能,請使用PDF/A-4

如果拿不定主意, PDF/A-3b能夠在現代性能和廣泛支援之間取得最佳平衡。


從零開始建立 PDF/A 文檔

既然您已經了解了 PDF/A 是什麼以及要針對哪個版本,那麼讓我們開始研究程式碼吧。 IronPDF 可以輕鬆地直接從 HTML 內容產生符合 PDF/A 標準的文檔,或將現有的 PDF 轉換為 PDF/A 格式。

安裝 IronPDF。

開始之前,請將 IronPDF NuGet 套件安裝到您的 .NET 專案中。 您可以透過 NuGet 套件管理器控制台、.NET CLI 或 Visual Studio NuGet UI 來完成此操作。

Install-Package IronPdf
Install-Package IronPdf
SHELL

或使用 .NET CLI:

dotnet add package IronPdf
dotnet add package IronPdf
SHELL

IronPDF 支援 .NET Framework 4.6.2+、.NET Core、.NET 5+ 和 .NET Standard 2.0,因此幾乎可以融入任何現代 .NET 項目,而無需擔心相容性問題。

將 HTML 渲染為 PDF/A

最常見的工作流程是從 HTML 內容產生 PDF 並直接以 PDF/A 格式儲存。 IronPDF 的ChromePdfRenderer處理 HTML 到 PDF 的轉換,而SaveAsPdfA方法一步完成合規性轉換。

:path=/static-assets/pdf/content-code-examples/tutorials/pdfa-archiving-csharp/pdfa-render-html-to-pdfa.cs
using IronPdf;

// Create HTML content for the document
string htmlContent = @"
<!DOCTYPE html>
<html>
<head>
    <style>
        body { font-family: Arial, sans-serif; margin: 40px; }
        h1 { color: #2c3e50; }
        .section { margin: 20px 0; }
        table { width: 100%; border-collapse: collapse; }
        th, td { border: 1px solid #ddd; padding: 10px; text-align: left; }
        th { background: #3498db; color: white; }
    </style>
</head>
<body>
    <h1>Quarterly Financial Report</h1>
    <p>Report Period: Q4 2025</p>
    <div class='section'>
        <table>
            <tr><th>Metric</th><th>Value</th></tr>
            <tr><td>Total Revenue</td><td>$4.2M</td></tr>
            <tr><td>Operating Expenses</td><td>$2.1M</td></tr>
            <tr><td>Net Income</td><td>$2.1M</td></tr>
        </table>
    </div>
    <p>This document is archived in PDF/A-3b format for long-term preservation.</p>
</body>
</html>";

// Render HTML to PDF
var renderer = new ChromePdfRenderer();
using var pdf = renderer.RenderHtmlAsPdf(htmlContent);

// Save as PDF/A-3b for archival compliance
pdf.SaveAsPdfA("quarterly-report-archived.pdf", PdfAVersions.PdfA3b);
Imports IronPdf

' Create HTML content for the document
Dim htmlContent As String = "
<!DOCTYPE html>
<html>
<head>
    <style>
        body { font-family: Arial, sans-serif; margin: 40px; }
        h1 { color: #2c3e50; }
        .section { margin: 20px 0; }
        table { width: 100%; border-collapse: collapse; }
        th, td { border: 1px solid #ddd; padding: 10px; text-align: left; }
        th { background: #3498db; color: white; }
    </style>
</head>
<body>
    <h1>Quarterly Financial Report</h1>
    <p>Report Period: Q4 2025</p>
    <div class='section'>
        <table>
            <tr><th>Metric</th><th>Value</th></tr>
            <tr><td>Total Revenue</td><td>$4.2M</td></tr>
            <tr><td>Operating Expenses</td><td>$2.1M</td></tr>
            <tr><td>Net Income</td><td>$2.1M</td></tr>
        </table>
    </div>
    <p>This document is archived in PDF/A-3b format for long-term preservation.</p>
</body>
</html>"

' Render HTML to PDF
Dim renderer As New ChromePdfRenderer()
Using pdf = renderer.RenderHtmlAsPdf(htmlContent)
    ' Save as PDF/A-3b for archival compliance
    pdf.SaveAsPdfA("quarterly-report-archived.pdf", PdfAVersions.PdfA3b)
End Using
$vbLabelText   $csharpLabel

輸出

在這個例子中,HTML 使用 IronPDF 基於 Chromium 的渲染引擎渲染成 PDF,從而確保與現代 Web 標準達到像素級的完美保真度。 SaveAsPdfA方法隨後嵌入所有必要的字體,根據需要轉換色彩空間,去除任何禁止的功能(如 JavaScript 或外部連結),並寫入符合規範的 XMP 元資料。 最終產生一個完全獨立的 PDF/A-3b 文件,可用於存檔儲存。

這種方法也能與 IronPDF 的其他渲染功能無縫搭配。 您可以新增頁首和頁尾、設定頁面大小和邊距、新增 CSS 樣式,並使用RenderingOptions來微調輸出—所有這些操作都可以在 PDF/A 轉換步驟之前完成。無論 PDF 是如何產生的, SaveAsPdfA呼叫都會處理合規性轉換。

將現有 PDF 轉換為 PDF/A

你不一定總是從HTML開始。 在許多實際場景中,您會收到現有的 PDF 檔案(來自掃描器、第三方系統、舊存檔或使用者上傳),並且需要將它們轉換為 PDF/A 格式以進行合規儲存。

IronPDF 使用相同的SaveAsPdfA方法處理此問題:

:path=/static-assets/pdf/content-code-examples/tutorials/pdfa-archiving-csharp/pdfa-convert-existing-pdf.cs
using IronPdf;

// Load an existing PDF file
using var pdf = PdfDocument.FromFile("existing-document.pdf");

// Convert and save as PDF/A-3b
// IronPDF automatically embeds fonts, converts color spaces, adds XMP metadata,
// and removes non-compliant features during conversion
pdf.SaveAsPdfA("existing-document-archived.pdf", PdfAVersions.PdfA3b);

// Alternative: Use ConvertToPdfA for in-memory conversion
using var pdf2 = PdfDocument.FromFile("another-document.pdf");
using var pdfA = pdf2.ConvertToPdfA(PdfAVersions.PdfA2b);
pdfA.SaveAs("another-document-archived.pdf");
Imports IronPdf

' Load an existing PDF file
Using pdf As PdfDocument = PdfDocument.FromFile("existing-document.pdf")
    ' Convert and save as PDF/A-3b
    ' IronPDF automatically embeds fonts, converts color spaces, adds XMP metadata,
    ' and removes non-compliant features during conversion
    pdf.SaveAsPdfA("existing-document-archived.pdf", PdfAVersions.PdfA3b)
End Using

' Alternative: Use ConvertToPdfA for in-memory conversion
Using pdf2 As PdfDocument = PdfDocument.FromFile("another-document.pdf")
    Using pdfA As PdfDocument = pdf2.ConvertToPdfA(PdfAVersions.PdfA2b)
        pdfA.SaveAs("another-document-archived.pdf")
    End Using
End Using
$vbLabelText   $csharpLabel

在轉換過程中,IronPDF 會分析現有的 PDF 文件並應用必要的轉換:嵌入任何引用但未包含的字體,將 RGB 或 CMYK 顏色空間轉換為適當的配置文件,添加所需的 XMP 元數據,並刪除任何不合規的功能,例如加密、多媒體或 JavaScript。 如果你想在記憶體中轉換而不立即儲存到磁碟,也可以使用ConvertToPdfA方法——這對於轉換後需要進行額外處理的管道非常有用。

這種模式非常適合需要將舊文檔儲存庫轉換為符合現代歸檔標準的遷移專案。


嵌入來源資料(PDF/A-3)

PDF/A-3 標準最強大的功能之一是能夠將任意文件(XML、CSV、JSON、電子表格或任何其他格式)直接嵌入到 PDF 文件中。 這使得 PDF 從純粹的視覺文件轉變為混合容器,將人類可讀的呈現方式和機器可讀的來源資料都包含在一個文件中。

將 XML/CSV 檔案與視覺化文件一起附加

核心工作流程非常簡單:產生或載入視覺化 PDF,將來源資料檔案作為嵌入式附件添加,然後另存為 PDF/A-3 格式。 IronPDF 支援透過ConvertToPdfA方法的多個重載來嵌入檔案—您可以直接將檔案路徑作為IEnumerable<string>傳遞。 IEnumerable<string>對於已在記憶體中的位元組數組,請使用EmbedFileByte對於基於流的工作流程,請使用EmbedFileStream 。 每種方法都完全符合 PDF/A 標準。

:path=/static-assets/pdf/content-code-examples/tutorials/pdfa-archiving-csharp/pdfa-embed-xml-attachment.cs
using IronPdf;
using System.Collections.Generic;

// Load the visual PDF document
using var pdf = PdfDocument.FromFile("financial-report.pdf");

// Prepare XML source data to embed
string xmlData = @"<?xml version='1.0' encoding='UTF-8'?>
<FinancialReport>
    <Period>Q4 2025</Period>
    <Revenue>4200000</Revenue>
    <Expenses>2100000</Expenses>
    <NetIncome>2100000</NetIncome>
</FinancialReport>";

byte[] xmlBytes = System.Text.Encoding.UTF8.GetBytes(xmlData);

// Configure the embedded file
var xmlConfig = new EmbedFileConfiguration(EmbedFileType.xml)
{
    EmbedFileName = "financial-data.xml",
    AFDesc = "Source financial data in XML format",
    AFRelationship = AFRelationship.Data
};

// Create embed file collection
var embedFiles = new List<EmbedFileByte>
{
    new EmbedFileByte(xmlBytes, xmlConfig)
};

// Convert to PDF/A-3b with embedded data
using var archivedPdf = pdf.ConvertToPdfA(embedFiles, PdfAVersions.PdfA3b);
archivedPdf.SaveAs("financial-report-with-data.pdf");
Imports IronPdf
Imports System.Collections.Generic
Imports System.Text

' Load the visual PDF document
Using pdf = PdfDocument.FromFile("financial-report.pdf")

    ' Prepare XML source data to embed
    Dim xmlData As String = "<?xml version='1.0' encoding='UTF-8'?>" & vbCrLf &
                            "<FinancialReport>" & vbCrLf &
                            "    <Period>Q4 2025</Period>" & vbCrLf &
                            "    <Revenue>4200000</Revenue>" & vbCrLf &
                            "    <Expenses>2100000</Expenses>" & vbCrLf &
                            "    <NetIncome>2100000</NetIncome>" & vbCrLf &
                            "</FinancialReport>"

    Dim xmlBytes As Byte() = Encoding.UTF8.GetBytes(xmlData)

    ' Configure the embedded file
    Dim xmlConfig As New EmbedFileConfiguration(EmbedFileType.xml) With {
        .EmbedFileName = "financial-data.xml",
        .AFDesc = "Source financial data in XML format",
        .AFRelationship = AFRelationship.Data
    }

    ' Create embed file collection
    Dim embedFiles As New List(Of EmbedFileByte) From {
        New EmbedFileByte(xmlBytes, xmlConfig)
    }

    ' Convert to PDF/A-3b with embedded data
    Using archivedPdf = pdf.ConvertToPdfA(embedFiles, PdfAVersions.PdfA3b)
        archivedPdf.SaveAs("financial-report-with-data.pdf")
    End Using

End Using
$vbLabelText   $csharpLabel

這種模式對於財務報告工作流程尤其有價值,其中可視化的 PDF 可能是格式化的資產負債表或損益表,而附加的 XML 或 CSV 文件則包含用於產生報告的原始資料。 審計人員可以檢查可視化文檔,並使用嵌入的來源資料獨立驗證底層數字—所有操作均可在單一文件中完成。您可以透過將其他檔案路徑或位元組陣列傳遞給ConvertToPdfA方法的集合參數,在同一文件中嵌入多個附件。

ZUGFeRD 和 Factur-X 電子發票合規性

ZUGFeRD(德國電子發票論壇中央使用者指南)及其國際對應標準 Factur-X 是電子發票標準,規定了結構化發票資料應如何嵌入 PDF/A-3 文件中。 可視化的 PDF 文件用作人可讀的發票,而嵌入的 XML 文件(遵循跨行業發票 (CII) 格式)則承載機器可處理的資料。

ZUGFeRD/Factur-X 合規性的關鍵要求如下:

PDF文件必須符合PDF/A-3b(至少)標準。 嵌入的 XML 檔案必須遵循 UN/CEFACT 跨行業發票模式。 XML 檔案必須依照標準規範命名(通常是 Factur-X 的檔案名稱為factur-x.xml ,ZUGFeRD 的zugferd-invoice.xml )。 必須設定特定的 XMP 元資料屬性,才能將文件標識為 ZUGFeRD/Factur-X 發票。

IronPDF 的EmbedFileConfiguration類別可以讓你對這些需求進行精細控制。 您可以設定ConformanceLevel (例如ConformanceLevel.XRECHNUNG )、 SchemaNamespaceSchemaPrefixPropertyVersionAFRelationship屬性,以符合目標系統期望的精確電子發票設定檔。

以下是如何使用 IronPDF 建立符合 ZUGFeRD 標準的發票:

:path=/static-assets/pdf/content-code-examples/tutorials/pdfa-archiving-csharp/pdfa-zugferd-invoice.cs
using IronPdf;
using System.Collections.Generic;

// Create visual invoice HTML
string invoiceHtml = @"
<!DOCTYPE html>
<html>
<head>
    <style>
        body { font-family: Arial, sans-serif; margin: 40px; }
        .header { border-bottom: 2px solid #e74c3c; padding-bottom: 15px; }
        h1 { color: #e74c3c; }
        .invoice-details { margin: 30px 0; }
        .line-item { display: flex; justify-content: space-between; padding: 10px 0; border-bottom: 1px solid #eee; }
        .total { font-size: 20px; font-weight: bold; margin-top: 20px; text-align: right; }
    </style>
</head>
<body>
    <div class='header'>
        <h1>INVOICE #INV-2026-0042</h1>
        <p>Date: February 7, 2026</p>
    </div>
    <div class='invoice-details'>
        <p><strong>Bill To:</strong> Acme Corporation</p>
        <p><strong>Address:</strong> 123 Business Ave, Suite 100</p>
    </div>
    <div class='line-item'><span>Software License (Enterprise)</span><span>$2,499.00</span></div>
    <div class='line-item'><span>Annual Support Contract</span><span>$499.00</span></div>
    <div class='line-item'><span>Implementation Services</span><span>$1,500.00</span></div>
    <div class='total'>Total: $4,498.00</div>
    <p style='margin-top: 40px; font-size: 12px; color: #666;'>
        This invoice complies with ZUGFeRD/Factur-X e-invoicing standards.
    </p>
</body>
</html>";

// Render the visual invoice
var renderer = new ChromePdfRenderer();
using var invoicePdf = renderer.RenderHtmlAsPdf(invoiceHtml);

// Prepare ZUGFeRD/Factur-X XML invoice data
string zugferdXml = @"<?xml version='1.0' encoding='UTF-8'?>
<rsm:CrossIndustryInvoice xmlns:rsm='urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100'>
    <rsm:ExchangedDocument>
        <ram:ID>INV-2026-0042</ram:ID>
        <ram:IssueDateTime>2026-02-07</ram:IssueDateTime>
    </rsm:ExchangedDocument>
    <rsm:SupplyChainTradeTransaction>
        <ram:ApplicableHeaderTradeSettlement>
            <ram:InvoiceCurrencyCode>USD</ram:InvoiceCurrencyCode>
            <ram:SpecifiedTradeSettlementHeaderMonetarySummation>
                <ram:GrandTotalAmount>4498.00</ram:GrandTotalAmount>
            </ram:SpecifiedTradeSettlementHeaderMonetarySummation>
        </ram:ApplicableHeaderTradeSettlement>
    </rsm:SupplyChainTradeTransaction>
</rsm:CrossIndustryInvoice>";

byte[] xmlBytes = System.Text.Encoding.UTF8.GetBytes(zugferdXml);

// Configure for ZUGFeRD/Factur-X compliance
var zugferdConfig = new EmbedFileConfiguration(EmbedFileType.xml)
{
    EmbedFileName = "factur-x.xml",
    AFDesc = "Factur-X Invoice Data",
    ConformanceLevel = ConformanceLevel.EN16931,
    SchemaNamespace = SchemaNamespace.facturX,
    SchemaPrefix = SchemaPrefix.fx,
    PropertyVersion = PropertyVersion.v1,
    AFRelationship = AFRelationship.Alternative
};

var embedFiles = new List<EmbedFileByte>
{
    new EmbedFileByte(xmlBytes, zugferdConfig)
};

// Convert to PDF/A-3b with embedded ZUGFeRD data
using var zugferdInvoice = invoicePdf.ConvertToPdfA(embedFiles, PdfAVersions.PdfA3b);

// Set invoice metadata
zugferdInvoice.MetaData.Title = "Invoice INV-2026-0042";
zugferdInvoice.MetaData.Author = "IronSoftware Billing";
zugferdInvoice.MetaData.Subject = "ZUGFeRD/Factur-X Compliant Invoice";

zugferdInvoice.SaveAs("invoice-zugferd.pdf");
Imports IronPdf
Imports System.Collections.Generic
Imports System.Text

' Create visual invoice HTML
Dim invoiceHtml As String = "
<!DOCTYPE html>
<html>
<head>
    <style>
        body { font-family: Arial, sans-serif; margin: 40px; }
        .header { border-bottom: 2px solid #e74c3c; padding-bottom: 15px; }
        h1 { color: #e74c3c; }
        .invoice-details { margin: 30px 0; }
        .line-item { display: flex; justify-content: space-between; padding: 10px 0; border-bottom: 1px solid #eee; }
        .total { font-size: 20px; font-weight: bold; margin-top: 20px; text-align: right; }
    </style>
</head>
<body>
    <div class='header'>
        <h1>INVOICE #INV-2026-0042</h1>
        <p>Date: February 7, 2026</p>
    </div>
    <div class='invoice-details'>
        <p><strong>Bill To:</strong> Acme Corporation</p>
        <p><strong>Address:</strong> 123 Business Ave, Suite 100</p>
    </div>
    <div class='line-item'><span>Software License (Enterprise)</span><span>$2,499.00</span></div>
    <div class='line-item'><span>Annual Support Contract</span><span>$499.00</span></div>
    <div class='line-item'><span>Implementation Services</span><span>$1,500.00</span></div>
    <div class='total'>Total: $4,498.00</div>
    <p style='margin-top: 40px; font-size: 12px; color: #666;'>
        This invoice complies with ZUGFeRD/Factur-X e-invoicing standards.
    </p>
</body>
</html>"

' Render the visual invoice
Dim renderer As New ChromePdfRenderer()
Using invoicePdf = renderer.RenderHtmlAsPdf(invoiceHtml)

    ' Prepare ZUGFeRD/Factur-X XML invoice data
    Dim zugferdXml As String = "<?xml version='1.0' encoding='UTF-8'?>
<rsm:CrossIndustryInvoice xmlns:rsm='urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100'>
    <rsm:ExchangedDocument>
        <ram:ID>INV-2026-0042</ram:ID>
        <ram:IssueDateTime>2026-02-07</ram:IssueDateTime>
    </rsm:ExchangedDocument>
    <rsm:SupplyChainTradeTransaction>
        <ram:ApplicableHeaderTradeSettlement>
            <ram:InvoiceCurrencyCode>USD</ram:InvoiceCurrencyCode>
            <ram:SpecifiedTradeSettlementHeaderMonetarySummation>
                <ram:GrandTotalAmount>4498.00</ram:GrandTotalAmount>
            </ram:SpecifiedTradeSettlementHeaderMonetarySummation>
        </ram:ApplicableHeaderTradeSettlement>
    </rsm:SupplyChainTradeTransaction>
</rsm:CrossIndustryInvoice>"

    Dim xmlBytes As Byte() = Encoding.UTF8.GetBytes(zugferdXml)

    ' Configure for ZUGFeRD/Factur-X compliance
    Dim zugferdConfig As New EmbedFileConfiguration(EmbedFileType.xml) With {
        .EmbedFileName = "factur-x.xml",
        .AFDesc = "Factur-X Invoice Data",
        .ConformanceLevel = ConformanceLevel.EN16931,
        .SchemaNamespace = SchemaNamespace.facturX,
        .SchemaPrefix = SchemaPrefix.fx,
        .PropertyVersion = PropertyVersion.v1,
        .AFRelationship = AFRelationship.Alternative
    }

    Dim embedFiles As New List(Of EmbedFileByte) From {
        New EmbedFileByte(xmlBytes, zugferdConfig)
    }

    ' Convert to PDF/A-3b with embedded ZUGFeRD data
    Using zugferdInvoice = invoicePdf.ConvertToPdfA(embedFiles, PdfAVersions.PdfA3b)

        ' Set invoice metadata
        zugferdInvoice.MetaData.Title = "Invoice INV-2026-0042"
        zugferdInvoice.MetaData.Author = "IronSoftware Billing"
        zugferdInvoice.MetaData.Subject = "ZUGFeRD/Factur-X Compliant Invoice"

        zugferdInvoice.SaveAs("invoice-zugferd.pdf")
    End Using
End Using
$vbLabelText   $csharpLabel

輸出

這種方法使您的發票系統能夠在一個符合標準的軟體包中產生既符合人工審核(可視化 PDF)又滿足自動處理(內嵌 XML)要求的文件。

審計追蹤保存

除了電子發票之外,PDF/A-3 的嵌入功能對於任何需要保持完整審計追蹤的工作流程都很有價值。 透過將原始來源資料、處理日誌或變更歷史記錄附加到最終文件中,您可以建立一個獨立的記錄,該記錄可以在將來的任何時間進行獨立驗證。

常見的審計追蹤嵌入模式包括:

財務報表-將原始會計資料(從您的 ERP 系統匯出的 CSV 或 XML 檔案)嵌入到格式化的財務報告旁邊。 審計人員無需存取原始系統即可驗證視覺化文件中的數字與來源資料是否一致。

監管文件-將原始提交資料、驗證結果和任何支持性計算作為嵌入式文件附在最終提交文件中。 這樣就產生了一個包含完整歸檔記錄的單一歸檔包。

合約管理-將版本歷史記錄、核准鍊或已簽署的元資料檔案嵌入到最終執行的合約 PDF 中。 這樣可以將文件的完整生命週期保存在單一歸檔文件中。

:path=/static-assets/pdf/content-code-examples/tutorials/pdfa-archiving-csharp/pdfa-audit-trail.cs
using IronPdf;
using System;
using System.Collections.Generic;
using System.Text.Json;

// Load the final document to archive
using var pdf = PdfDocument.FromFile("executed-contract.pdf");

// Create audit trail data
var auditTrail = new
{
    DocumentId = "CONTRACT-2026-00142",
    CreatedDate = "2026-01-15T09:30:00Z",
    FinalizedDate = "2026-02-07T14:22:00Z",
    Versions = new[]
    {
        new { Version = 1, Date = "2026-01-15", Action = "Draft created", User = "john.smith@company.com" },
        new { Version = 2, Date = "2026-01-20", Action = "Legal review completed", User = "legal@company.com" },
        new { Version = 3, Date = "2026-02-01", Action = "Client revisions incorporated", User = "john.smith@company.com" },
        new { Version = 4, Date = "2026-02-07", Action = "Final execution", User = "ceo@company.com" }
    },
    Signatures = new[]
    {
        new { Signer = "Company CEO", SignedDate = "2026-02-07T14:20:00Z", IPAddress = "192.168.1.100" },
        new { Signer = "Client Representative", SignedDate = "2026-02-07T14:22:00Z", IPAddress = "10.0.0.50" }
    },
    Checksum = "SHA256:a1b2c3d4e5f6..."
};

string auditJson = JsonSerializer.Serialize(auditTrail, new JsonSerializerOptions { WriteIndented = true });
byte[] auditBytes = System.Text.Encoding.UTF8.GetBytes(auditJson);

// Configure audit trail attachment
var auditConfig = new EmbedFileConfiguration(EmbedFileType.xml)
{
    EmbedFileName = "audit-trail.json",
    AFDesc = "Complete document audit trail and version history",
    AFRelationship = AFRelationship.Supplement
};

// Create validation log
string validationLog = @"
Validation Report
=================
Document: CONTRACT-2026-00142
Validated: 2026-02-07T14:25:00Z

Checks Performed:
[PASS] All required fields present
[PASS] Signature blocks completed
[PASS] Date formats valid
[PASS] Currency amounts verified
[PASS] Legal clauses match template v2.1

Final Status: APPROVED FOR ARCHIVAL
";

byte[] validationBytes = System.Text.Encoding.UTF8.GetBytes(validationLog);

var validationConfig = new EmbedFileConfiguration(EmbedFileType.xml)
{
    EmbedFileName = "validation-report.txt",
    AFDesc = "Pre-archive validation report",
    AFRelationship = AFRelationship.Supplement
};

// Embed both files
var embedFiles = new List<EmbedFileByte>
{
    new EmbedFileByte(auditBytes, auditConfig),
    new EmbedFileByte(validationBytes, validationConfig)
};

// Convert to PDF/A-3b with full audit trail
using var archivedContract = pdf.ConvertToPdfA(embedFiles, PdfAVersions.PdfA3b);

// Set archival metadata
archivedContract.MetaData.Title = "Executed Contract - CONTRACT-2026-00142";
archivedContract.MetaData.Author = "Contract Management System";
archivedContract.MetaData.Subject = "Fully executed agreement with audit trail";
archivedContract.MetaData.Keywords = "contract, executed, 2026, archived";

archivedContract.SaveAs("contract-archived-with-audit.pdf");
Imports IronPdf
Imports System
Imports System.Collections.Generic
Imports System.Text.Json

' Load the final document to archive
Using pdf = PdfDocument.FromFile("executed-contract.pdf")

    ' Create audit trail data
    Dim auditTrail = New With {
        .DocumentId = "CONTRACT-2026-00142",
        .CreatedDate = "2026-01-15T09:30:00Z",
        .FinalizedDate = "2026-02-07T14:22:00Z",
        .Versions = New Object() {
            New With {.Version = 1, .Date = "2026-01-15", .Action = "Draft created", .User = "john.smith@company.com"},
            New With {.Version = 2, .Date = "2026-01-20", .Action = "Legal review completed", .User = "legal@company.com"},
            New With {.Version = 3, .Date = "2026-02-01", .Action = "Client revisions incorporated", .User = "john.smith@company.com"},
            New With {.Version = 4, .Date = "2026-02-07", .Action = "Final execution", .User = "ceo@company.com"}
        },
        .Signatures = New Object() {
            New With {.Signer = "Company CEO", .SignedDate = "2026-02-07T14:20:00Z", .IPAddress = "192.168.1.100"},
            New With {.Signer = "Client Representative", .SignedDate = "2026-02-07T14:22:00Z", .IPAddress = "10.0.0.50"}
        },
        .Checksum = "SHA256:a1b2c3d4e5f6..."
    }

    Dim auditJson As String = JsonSerializer.Serialize(auditTrail, New JsonSerializerOptions With {.WriteIndented = True})
    Dim auditBytes As Byte() = System.Text.Encoding.UTF8.GetBytes(auditJson)

    ' Configure audit trail attachment
    Dim auditConfig = New EmbedFileConfiguration(EmbedFileType.xml) With {
        .EmbedFileName = "audit-trail.json",
        .AFDesc = "Complete document audit trail and version history",
        .AFRelationship = AFRelationship.Supplement
    }

    ' Create validation log
    Dim validationLog As String = "
Validation Report
=================
Document: CONTRACT-2026-00142
Validated: 2026-02-07T14:25:00Z

Checks Performed:
[PASS] All required fields present
[PASS] Signature blocks completed
[PASS] Date formats valid
[PASS] Currency amounts verified
[PASS] Legal clauses match template v2.1

Final Status: APPROVED FOR ARCHIVAL
"

    Dim validationBytes As Byte() = System.Text.Encoding.UTF8.GetBytes(validationLog)

    Dim validationConfig = New EmbedFileConfiguration(EmbedFileType.xml) With {
        .EmbedFileName = "validation-report.txt",
        .AFDesc = "Pre-archive validation report",
        .AFRelationship = AFRelationship.Supplement
    }

    ' Embed both files
    Dim embedFiles = New List(Of EmbedFileByte) From {
        New EmbedFileByte(auditBytes, auditConfig),
        New EmbedFileByte(validationBytes, validationConfig)
    }

    ' Convert to PDF/A-3b with full audit trail
    Using archivedContract = pdf.ConvertToPdfA(embedFiles, PdfAVersions.PdfA3b)

        ' Set archival metadata
        archivedContract.MetaData.Title = "Executed Contract - CONTRACT-2026-00142"
        archivedContract.MetaData.Author = "Contract Management System"
        archivedContract.MetaData.Subject = "Fully executed agreement with audit trail"
        archivedContract.MetaData.Keywords = "contract, executed, 2026, archived"

        archivedContract.SaveAs("contract-archived-with-audit.pdf")
    End Using
End Using
$vbLabelText   $csharpLabel

驗證 PDF/A 合規性

建立文件並將其命名為 PDF/A 是不夠的——您還需要驗證輸出是否真正符合標準的要求。 聲稱是 PDF/A 格式但未通過驗證的文件將不會被存檔系統、政府入口網站或電子發票平台接受。

IronPDF 的SaveAsPdfAConvertToPdfA方法可以處理合規性轉換的繁重工作——嵌入字體、轉換顏色空間、移除禁止的功能以及寫入 XMP 元資料。 但是,為了獨立驗證輸出結果,您應該使用專用的外部工具進行驗證,例如veraPDF (業界標準的開源 PDF/A 驗證器)或 Adobe Acrobat Pro 的內建預檢工具。 將 veraPDF 整合到您的 CI/CD 管道或文件處理工作流程中,可讓您獲得權威的第三方確認,確保產生的每個文件在儲存或分發之前都符合所宣稱的標準。

常見合規性問題及解決方法

即使 IronPDF 處理了大部分合規性工作,某些輸入條件仍可能導致驗證失敗。 以下是一些最常見的問題以及解決方法:

未嵌入字體-這是最常見的故障。 如果來源 PDF 透過名稱引用字體,但沒有嵌入字體數據,則輸出將不符合 PDF/A 標準。 IronPDF 會在轉換過程中嘗試自動嵌入字體,但如果 IronPDF 運行的系統上沒有字體文件,則嵌入會失敗。 解決方法:確保原始文件中使用的所有字型都已安裝在伺服器上,或在 HTML 內容中使用通用的 Web 安全字型。

不支援的色彩空間— PDF/A 要求所有色彩資料都必須在特定的嵌入式色彩設定檔中定義(通常螢幕文件使用 sRGB 設定文件,列印文件使用 CMYK 設定檔)。 使用裝置相關色彩空間且沒有嵌入式設定檔的來源 PDF 檔案將無法通過驗證。 修正: IronPDF 在大多數情況下會自動處理色彩空間轉換。 對於特殊情況,請確保您的來源內容以 sRGB 格式指定顏色。

加密或密碼保護-PDF/A 嚴格禁止加密。 如果要轉換受密碼保護的 PDF 文件,必須先解密。解決方法:在轉換之前,使用PdfDocument.FromFile(&quot;encrypted.pdf&quot;, &quot;password&quot;)開啟受保護的檔案。

JavaScript 或多媒體內容— PDF/A 禁止使用 JavaScript、音訊、視訊和其他互動元素。 如果您的來源 HTML 包含

Ahmad Sohail
全堆疊開發人員

Ahmad 是一名全堆疊開發人員,在 C#、Python 和 Web 技術方面有深厚的基礎。

在加入 Iron Software 團隊之前,Ahmad 從事自動化專案和 API 整合工作,專注於改善效能和開發人員體驗。

在空閒時間,他喜歡嘗試 UI/UX 想法,為開源工具貢獻心力,偶爾也會鑽研技術撰寫和文件,讓複雜的主題更容易理解。

準備好開始了嗎?
Nuget 下載 17,386,124 | 版本: 2026.2 剛剛發布