How to Archive PDFs with PDF/A Compliance in C
透過 IronPDF 在 C# 中實現 PDF/A 合規性,為 .NET 開發人員提供了一條直接途徑,用以建立、轉換及驗證符合 ISO 19005 標準的歸檔 PDF 檔案——確保文件在任何系統上都能呈現一致的樣式,無論是現在還是數十年後。 從將 HTML 渲染為 PDF/A,到將現有檔案轉換為 PDF/A-1b、PDF/A-2b 或 PDF/A-3b,再到嵌入源資料以符合 ZUGFeRD 和 Factur-X 電子發票規範,IronPDF 能在不離開 .NET 生態系統的情況下,完整處理整個 PDF/A 轉換工作流程。
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:
購買 IronPDF 或註冊 30 天試用版後,請在應用程式啟動時輸入您的授權金鑰。
IronPdf.License.LicenseKey = "KEY";
IronPdf.License.LicenseKey = "KEY";
Imports IronPdf
IronPdf.License.LicenseKey = "KEY"
目錄
- 了解 PDF/A
- 建立 PDF/A 文件
- 進階 PDF/A 工作流程
- 實際歸檔情境
什麼是 PDF/A,它為何重要?
PDF/A 是 PDF 格式(ISO 19005)中符合 ISO 標準的子集,專為電子文件的長期、可靠歸檔而設計。 與標準 PDF 不同,標準 PDF 可引用外部字型、連結至外部內容,並依賴系統特定的渲染行為;而 PDF/A 檔案則是完全自包含的。 文件渲染所需的每種字型、色彩設定檔及元資料,皆已直接嵌入檔案中。
這點至關重要,因為 PDF/A 文件無論是在今天或 100 年後開啟,只要使用符合標準的檢視器,無論作業系統或軟體版本為何,都能呈現完全相同的樣貌。 翻譯內容不依賴可能消失的外部資源,無需特定字型安裝,且在顏色或透明度的呈現方式上不存在歧義。
除了技術上的穩定性外,符合 PDF/A 標準往往是一項硬性要求——而不僅僅是最佳實踐。強制要求使用 PDF/A 的產業與機構包括:
法律與司法體系 — 美國、歐盟及許多其他司法管轄區的法院,均要求或強烈建議使用 PDF/A 格式進行電子提交。 美國聯邦法院系統的 CM/ECF 提交標準中,將 PDF/A 列為長期檔案保存的首選格式。
政府機關 — 美國國家檔案與紀錄管理局(NARA)指定 PDF/A 為傳輸永久性電子紀錄的認可格式。 同樣地,歐盟委員會規定特定官方出版物及法規申報文件必須採用 PDF/A 格式。
金融服務與稽核 — 美國證券交易委員會(SEC)等監管機構接受 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 相同的合規等級(2b 和 2a),並新增一個等級: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 合規等級遵循相同模式: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 版本取決於您的具體需求:

最大相容性:針對現有系統、驗證工具及檢視器(特別是在法律與政府領域),請使用 PDF/A-1b 或 PDF/A-2b 格式。
電子發票:針對 ZUGFeRD、Factur-X 或類似需嵌入原始資料的標準,請使用 PDF/A-3b 格式。
無障礙規範遵循:針對第 508 條或 WCAG 要求,請選擇您所使用版本的 a 合規等級(PDF/A-2a 或 PDF/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 使用者介面來執行此操作。
Install-Package IronPdf
Install-Package IronPdf
或使用 .NET CLI:
dotnet add package IronPdf
dotnet add package IronPdf
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 = @"
E html>
le>
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; }
yle>
Quarterly Financial Report</h1>
eport Period: Q4 2025</p>
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>
v>
his document is archived in PDF/A-3b format for long-term preservation.</p>
;
// 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
輸出
在此範例中,HTML 會透過 IronPDF 基於 Chromium 的渲染引擎轉換為 PDF,此引擎能確保與現代網頁標準完全一致,呈現像素級的精準度。 SaveAsPdfA 方法會將所有必需的字型嵌入文件中,視需要轉換色彩空間,移除任何受限功能(例如 JavaScript 或外部連結),並寫入符合規範的 XMP 元資料。 最終產出為一個完全自包含的 PDF/A-3b 檔案,可直接用於歸檔儲存。
此方法亦能與 IronPDF 的其他渲染功能無縫整合。 您可以在 PDF/A 轉換步驟之前,套用頁首和頁尾、設定頁面尺寸與邊距、加入 CSS 樣式,並使用 RenderingOptions 來微調輸出內容。無論 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
轉換過程中,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>,使用 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'?>
alReport>
iod>Q4 2025</Period>
enue>4200000</Revenue>
enses>2100000</Expenses>
Income>2100000</NetIncome>
ialReport>";
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'?>
<FinancialReport>
<Period>Q4 2025</Period>
<Revenue>4200000</Revenue>
<Expenses>2100000</Expenses>
<NetIncome>2100000</NetIncome>
</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
此模式對於財務報表工作流程尤為重要,在此情境下,視覺化的 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(例如 PropertyVersion 及 AFRelationship 等屬性,以符合目標系統所要求的電子發票設定檔。
以下是您如何使用 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 = @"
E html>
le>
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; }
yle>
class='header'>
<h1>INVOICE #INV-2026-0042</h1>
<p>Date: February 7, 2026</p>
v>
class='invoice-details'>
<p><strong>Bill To:</strong> Acme Corporation</p>
<p><strong>Address:</strong> 123 Business Ave, Suite 100</p>
v>
class='line-item'><span>Software License (Enterprise)</span><span>$2,499.00</span></div>
class='line-item'><span>Annual Support Contract</span><span>$499.00</span></div>
class='line-item'><span>Implementation Services</span><span>$1,500.00</span></div>
class='total'>Total: $4,498.00</div>
tyle='margin-top: 40px; font-size: 12px; color: #666;'>
This invoice complies with ZUGFeRD/Factur-X e-invoicing standards.
;
// 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'?>
ssIndustryInvoice xmlns:rsm='urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100'>
:ExchangedDocument>
<ram:ID>INV-2026-0042</ram:ID>
<ram:IssueDateTime>2026-02-07</ram:IssueDateTime>
m:ExchangedDocument>
:SupplyChainTradeTransaction>
<ram:ApplicableHeaderTradeSettlement>
<ram:InvoiceCurrencyCode>USD</ram:InvoiceCurrencyCode>
<ram:SpecifiedTradeSettlementHeaderMonetarySummation>
<ram:GrandTotalAmount>4498.00</ram:GrandTotalAmount>
</ram:SpecifiedTradeSettlementHeaderMonetarySummation>
</ram:ApplicableHeaderTradeSettlement>
m:SupplyChainTradeTransaction>
ossIndustryInvoice>";
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
輸出
此方法可讓您的開票系統生成符合標準的單一套件,其文件既能滿足人工審核需求(視覺化 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 = @"
on Report
=========
: CONTRACT-2026-00142
d: 2026-02-07T14:25:00Z
erformed:
ll required fields present
ignature blocks completed
ate formats valid
urrency amounts verified
egal clauses match template v2.1
atus: 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 As 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 = "
on Report
=========
: CONTRACT-2026-00142
d: 2026-02-07T14:25:00Z
erformed:
ll required fields present
ignature blocks completed
ate formats valid
urrency amounts verified
egal clauses match template v2.1
atus: APPROVED FOR ARCHIVAL
"
Dim validationBytes As Byte() = System.Text.Encoding.UTF8.GetBytes(validationLog)
Dim validationConfig As New EmbedFileConfiguration(EmbedFileType.xml) With {
.EmbedFileName = "validation-report.txt",
.AFDesc = "Pre-archive validation report",
.AFRelationship = AFRelationship.Supplement
}
' Embed both files
Dim embedFiles As 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
驗證 PDF/A 合規性
僅僅建立文件並將其命名為 PDF/A 是不夠的——您還需要驗證輸出結果是否確實符合該標準的要求。 聲稱符合 PDF/A 標準卻無法通過驗證的檔案,將無法被檔案系統、政府入口網站或電子發票平台所接受。
IronPDF 的 SaveAsPdfA 和 ConvertToPdfA 方法負責處理合規轉換中的繁重工作——包括嵌入字型、轉換色彩空間、移除受限功能,以及寫入 XMP 元資料。 然而,若需對輸出結果進行獨立驗證,應使用專用的外部工具進行驗證,例如 veraPDF(業界標準的開源 PDF/A 驗證工具)或 Adobe Acrobat Pro 內建的 Preflight 工具。 將 veraPDF 整合至您的 CI/CD 管道或文件處理工作流程中,可讓您獲得權威的第三方確認,確保每個產出的檔案在儲存或分發前,皆符合聲稱的標準。
常見合規性錯誤與修正方案
即使 IronPDF 已處理大部分的合規工作,某些輸入條件仍可能導致驗證失敗。 以下是常見問題及其解決方法:
非內嵌字型 — 這是最常見的單一錯誤。 若原始 PDF 文件僅以名稱引用字型但未嵌入字型資料,輸出檔案將不符合 PDF/A 標準。 IronPDF 會在轉換過程中嘗試自動嵌入字型,但如果 IronPDF 所處的系統上沒有該字型檔案,嵌入操作將會失敗。 修正:請確保源文件中使用的所有字型均已安裝於伺服器上,或在 HTML 內容中使用普遍可用的網頁安全字型。
不支援的色彩空間 — PDF/A 要求所有色彩資料必須定義在特定的內嵌色彩配置檔中(通常為螢幕導向文件使用的 sRGB,或印刷用的 CMYK 配置檔)。 若原始 PDF 文件使用依賴裝置的色彩空間且未嵌入色彩配置檔,將無法通過驗證。 修正:IronPDF 在大多數情況下會自動處理色彩空間轉換。 針對特殊情況,請確保原始內容中的顏色均採用 sRGB 色域標示。
加密或密碼保護 — PDF/A 嚴格禁止加密。 若您要轉換受密碼保護的 PDF 檔案,必須先進行解密。解決方法:在轉換前,請使用 PdfDocument.FromFile("encrypted.pdf", "password") 來開啟受保護的檔案。
JavaScript 或多媒體內容 — PDF/A 禁止使用 JavaScript、音訊、影片及其他互動式元素。 若原始 HTML 包含 <script> 標籤、嵌入式影片或互動式表單,請務必將其移除,否則轉換過程會自動刪除這些內容。 修正:請確保您的 HTML 內容在渲染為 PDF/A 之前是靜態的。
透明度問題(僅限 PDF/A-1)— PDF/A-1 不支援透明度。 若您的文件包含透明元素(常見於現代 CSS 版面配置),轉換為 PDF/A-1 格式時將需要進行扁平化處理。 修正:若您的文件使用透明度,請將目標設定為 PDF/A-2 或更高版本;若目標格式為 PDF/A-1,請確保 CSS 未使用 rgba 或透明 PNG 圖檔。
字型、色彩空間與元資料要求
了解 PDF/A 合規性的三大支柱——字型、色彩空間與元資料——有助於您設計出首次提交即能通過驗證的文件。
字型:文件中使用的所有字型必須完全嵌入。 這包含文本中出現的所有字形,而不僅是其中一部分。 針對 PDF/A-2a 及 PDF/A-3a 符合性等級,每個字元都必須對應 Unicode 編碼,以確保文字能被可靠地擷取與搜尋。
using IronPDF 的 HTML 轉 PDF 渲染功能時,Chromium 引擎會自動嵌入系統中可用的字型。 為確保在不同部署環境(開發、預備、生產)間的一致性,建議考慮透過 HTML 中的 <link> 標籤載入 Google Fonts,或將字型檔案封裝至應用程式中,並透過 CSS @font-face 進行引用。
色彩空間:PDF/A 規範要求所有顏色必須在由 ICC 色域設定檔支援的裝置獨立色彩空間內進行指定。實際上,這意味著大多數文件應使用 sRGB。 IronPDF 會在 SaveAsPdfA 處理過程中嵌入適當的 ICC 色域設定檔並自動轉換顏色 — 若您的工作流程需要特定色域設定檔,亦可傳入自訂的 ICC 檔案路徑。然而,若您處理的是需要 CMYK 精準度的印刷導向文件,請確保原始內容使用適合 CMYK 的色域設定檔,並在轉換過程中保留這些設定。
元資料:PDF/A 要求將 XMP(可擴展元資料平台)元資料嵌入文件中。 這包括文件標題、作者、建立日期、修改日期,以及 PDF/A 符合性等級識別碼。 IronPDF 會自動填入這些欄位,但您也可以透過 MetaData 屬性明確設定,以獲得更細緻的控制:
:path=/static-assets/pdf/content-code-examples/tutorials/pdfa-archiving-csharp/pdfa-metadata-settings.cs
using IronPdf;
using System;
// Create a PDF document
var renderer = new ChromePdfRenderer();
using var pdf = renderer.RenderHtmlAsPdf("<h1>Annual Report 2025</h1><p>Corporate performance summary.</p>");
// Set standard metadata properties
pdf.MetaData.Title = "Annual Report 2025 - IronSoftware Inc.";
pdf.MetaData.Author = "Finance Department";
pdf.MetaData.Subject = "Corporate annual financial and operational report";
pdf.MetaData.Keywords = "annual report, financial, 2025, corporate, IronSoftware";
pdf.MetaData.Creator = "IronPDF Document Generator";
pdf.MetaData.CreationDate = DateTime.Now;
pdf.MetaData.ModifiedDate = DateTime.Now;
// For custom or batch metadata, use SetMetaDataDictionary
var metadataDict = new System.Collections.Generic.Dictionary<string, string>
{
{ "Title", "Quarterly Report Q4 2025" },
{ "Author", "Finance Team" },
{ "Subject", "Q4 Financial Results" },
{ "Keywords", "quarterly, Q4, 2025, finance" },
{ "Department", "Finance" },
{ "Classification", "Internal" },
{ "RetentionPeriod", "7 years" }
};
using var pdf2 = renderer.RenderHtmlAsPdf("<h1>Q4 Report</h1>");
pdf2.MetaData.SetMetaDataDictionary(metadataDict);
// Convert to PDF/A with metadata preserved
pdf.SaveAsPdfA("annual-report-2025.pdf", PdfAVersions.PdfA3b);
pdf2.SaveAsPdfA("q4-report-2025.pdf", PdfAVersions.PdfA3b);
Imports IronPdf
Imports System
Imports System.Collections.Generic
' Create a PDF document
Dim renderer As New ChromePdfRenderer()
Using pdf = renderer.RenderHtmlAsPdf("<h1>Annual Report 2025</h1><p>Corporate performance summary.</p>")
' Set standard metadata properties
pdf.MetaData.Title = "Annual Report 2025 - IronSoftware Inc."
pdf.MetaData.Author = "Finance Department"
pdf.MetaData.Subject = "Corporate annual financial and operational report"
pdf.MetaData.Keywords = "annual report, financial, 2025, corporate, IronSoftware"
pdf.MetaData.Creator = "IronPDF Document Generator"
pdf.MetaData.CreationDate = DateTime.Now
pdf.MetaData.ModifiedDate = DateTime.Now
' For custom or batch metadata, use SetMetaDataDictionary
Dim metadataDict As New Dictionary(Of String, String) From {
{"Title", "Quarterly Report Q4 2025"},
{"Author", "Finance Team"},
{"Subject", "Q4 Financial Results"},
{"Keywords", "quarterly, Q4, 2025, finance"},
{"Department", "Finance"},
{"Classification", "Internal"},
{"RetentionPeriod", "7 years"}
}
Using pdf2 = renderer.RenderHtmlAsPdf("<h1>Q4 Report</h1>")
pdf2.MetaData.SetMetaDataDictionary(metadataDict)
' Convert to PDF/A with metadata preserved
pdf.SaveAsPdfA("annual-report-2025.pdf", PdfAVersions.PdfA3b)
pdf2.SaveAsPdfA("q4-report-2025.pdf", PdfAVersions.PdfA3b)
End Using
End Using
對於將被記錄管理系統索引的文件而言,明確設定元數據尤為重要,因為標題和作者欄位常被用於目錄編製和搜尋。
政府檔案管理應用案例
PDF/A 不僅是一項技術規範——在許多政府、法律及醫療保健領域中,它更是實務上的必要要求。 在本節中,我們將探討 PDF/A 如何符合特定的法規框架,以及您需要了解哪些內容才能透過 IronPDF 滿足這些要求。
NARA 要求(美國國家檔案館)
美國國家檔案與紀錄管理局(NARA)負責保存具有永久價值的聯邦檔案。 美國國家檔案與記錄管理局(NARA)的移交指南明確指出,PDF/A 是將永久性電子記錄移交至國家檔案館的首選格式之一。
NARA 針對 PDF/A 提交文件的主要要求:
NARA 接受大多數記錄類型的 PDF/A-1、PDF/A-2 及 PDF/A-3 格式。文件在移交前,必須針對聲稱的 PDF/A 版本進行驗證。 元資料必須包含建立機構、檔案系列識別碼及涵蓋的日期範圍。 必須包含內嵌字型 — 美國國家檔案與紀錄管理局 (NARA) 明確拒絕接受缺少字型或僅引用字型的文件。 針對數位化(掃描)檔案,美國國家檔案與紀錄管理局(NARA)建議最低解析度為 300 DPI,並因應其優化的影像壓縮效果,優先採用 PDF/A-2 或更高版本。
以下是您可能需要如何準備一批機構檔案以移交至美國國家檔案與紀錄管理局(NARA):
輸入

:path=/static-assets/pdf/content-code-examples/tutorials/pdfa-archiving-csharp/pdfa-nara-compliance.cs
using IronPdf;
using System;
using System.IO;
string inputFolder = "agency-records/";
string validatedFolder = "nara-transfer/validated/";
string rejectedFolder = "nara-transfer/rejected/";
// Create output directories
Directory.CreateDirectory(validatedFolder);
Directory.CreateDirectory(rejectedFolder);
// NARA transfer metadata requirements
string agencyName = "Department of Example";
string recordSeries = "Administrative Correspondence";
string dateRange = "2020-2025";
// Process all PDF files in the input folder
string[] pdfFiles = Directory.GetFiles(inputFolder, "*.pdf");
Console.WriteLine($"Preparing {pdfFiles.Length} records for NARA transfer");
Console.WriteLine($"Agency: {agencyName}");
Console.WriteLine($"Record Series: {recordSeries}");
Console.WriteLine();
int successCount = 0;
int failCount = 0;
foreach (string inputPath in pdfFiles)
{
string fileName = Path.GetFileName(inputPath);
try
{
using var pdf = PdfDocument.FromFile(inputPath);
// Set NARA-required metadata
var metadata = new System.Collections.Generic.Dictionary<string, string>
{
{ "Title", Path.GetFileNameWithoutExtension(inputPath) },
{ "Author", agencyName },
{ "Subject", recordSeries },
{ "Keywords", $"NARA, {recordSeries}, {dateRange}" },
{ "Agency", agencyName },
{ "RecordSeries", recordSeries },
{ "DateRange", dateRange },
{ "TransferDate", DateTime.Now.ToString("yyyy-MM-dd") }
};
pdf.MetaData.SetMetaDataDictionary(metadata);
// Convert to PDF/A-2b (NARA preferred for digitized records)
string outputPath = Path.Combine(validatedFolder, fileName);
pdf.SaveAsPdfA(outputPath, PdfAVersions.PdfA2b);
// Verify the output
using var verifyPdf = PdfDocument.FromFile(outputPath);
if (verifyPdf.PageCount > 0)
{
successCount++;
Console.WriteLine($"[OK] {fileName}");
}
else
{
throw new Exception("Output PDF has no pages");
}
}
catch (Exception ex)
{
failCount++;
Console.WriteLine($"[FAILED] {fileName}: {ex.Message}");
// Move original to rejected folder for manual review
try
{
File.Copy(inputPath, Path.Combine(rejectedFolder, fileName), overwrite: true);
}
catch { }
}
}
Console.WriteLine();
Console.WriteLine("=== NARA Transfer Preparation Complete ===");
Console.WriteLine($"Successfully converted: {successCount}");
Console.WriteLine($"Failed (requires review): {failCount}");
Console.WriteLine($"Output location: {validatedFolder}");
Imports IronPdf
Imports System
Imports System.IO
Module Program
Sub Main()
Dim inputFolder As String = "agency-records/"
Dim validatedFolder As String = "nara-transfer/validated/"
Dim rejectedFolder As String = "nara-transfer/rejected/"
' Create output directories
Directory.CreateDirectory(validatedFolder)
Directory.CreateDirectory(rejectedFolder)
' NARA transfer metadata requirements
Dim agencyName As String = "Department of Example"
Dim recordSeries As String = "Administrative Correspondence"
Dim dateRange As String = "2020-2025"
' Process all PDF files in the input folder
Dim pdfFiles As String() = Directory.GetFiles(inputFolder, "*.pdf")
Console.WriteLine($"Preparing {pdfFiles.Length} records for NARA transfer")
Console.WriteLine($"Agency: {agencyName}")
Console.WriteLine($"Record Series: {recordSeries}")
Console.WriteLine()
Dim successCount As Integer = 0
Dim failCount As Integer = 0
For Each inputPath As String In pdfFiles
Dim fileName As String = Path.GetFileName(inputPath)
Try
Using pdf = PdfDocument.FromFile(inputPath)
' Set NARA-required metadata
Dim metadata As New System.Collections.Generic.Dictionary(Of String, String) From {
{"Title", Path.GetFileNameWithoutExtension(inputPath)},
{"Author", agencyName},
{"Subject", recordSeries},
{"Keywords", $"NARA, {recordSeries}, {dateRange}"},
{"Agency", agencyName},
{"RecordSeries", recordSeries},
{"DateRange", dateRange},
{"TransferDate", DateTime.Now.ToString("yyyy-MM-dd")}
}
pdf.MetaData.SetMetaDataDictionary(metadata)
' Convert to PDF/A-2b (NARA preferred for digitized records)
Dim outputPath As String = Path.Combine(validatedFolder, fileName)
pdf.SaveAsPdfA(outputPath, PdfAVersions.PdfA2b)
' Verify the output
Using verifyPdf = PdfDocument.FromFile(outputPath)
If verifyPdf.PageCount > 0 Then
successCount += 1
Console.WriteLine($"[OK] {fileName}")
Else
Throw New Exception("Output PDF has no pages")
End If
End Using
End Using
Catch ex As Exception
failCount += 1
Console.WriteLine($"[FAILED] {fileName}: {ex.Message}")
' Move original to rejected folder for manual review
Try
File.Copy(inputPath, Path.Combine(rejectedFolder, fileName), overwrite:=True)
Catch
End Try
End Try
Next
Console.WriteLine()
Console.WriteLine("=== NARA Transfer Preparation Complete ===")
Console.WriteLine($"Successfully converted: {successCount}")
Console.WriteLine($"Failed (requires review): {failCount}")
Console.WriteLine($"Output location: {validatedFolder}")
End Sub
End Module
輸出

在為 NARA 移交準備檔案時,必須逐一驗證每個檔案。 NARA 的資料導入流程會拒絕不符合規範的檔案,而重新處理大量批次檔案將耗費大量時間與精力。 將驗證功能直接整合至轉換流程中——例如在每次 SaveAsPdfA 呼叫後使用 veraPDF 等工具——是最佳的解決方案。
法院文件歸檔
美國聯邦法院系統及許多州級法院系統均採用電子提交系統(聯邦層級主要為 CM/ECF),該系統接受或要求使用 PDF/A 格式進行長期檔案保存。 雖然具體要求因司法管轄區而異,但一般期望是相通的:
聯邦法院 — 美國法院行政辦公室建議,將成為永久案件檔案一部分的文件應採用 PDF/A 格式。 CM/ECF 系統通常將 PDF/A-1b 視為最低標準,但對於格式複雜的文件,PDF/A-2b 正逐漸成為首選。
各州法院 — 要求差異甚大。 部分州份(如德克薩斯州和加利福尼亞州)針對特定申報類型設有明確的 PDF/A 要求,而其他州份則僅將其列為最佳實踐建議。務必查閱目標司法管轄區的具體規定。
各法院系統的共通需求包括:
文件必須支援文字搜尋(而非僅為掃描圖像),這意味著應盡可能採用 PDF/A-1a 或 PDF/A-2a 格式,或確保已對掃描文件進行 OCR 處理。 頁面尺寸必須符合標準規格(通常為 US Letter,8.5 英吋 × 11 英吋)。 元資料應包含案件編號、提交日期,以及文件類型(若提交系統支援此功能)。
:path=/static-assets/pdf/content-code-examples/tutorials/pdfa-archiving-csharp/pdfa-court-filing.cs
using IronPdf;
using System;
// Court filing configuration
string caseNumber = "1:26-cv-00142-ABC";
string courtName = "US District Court, Northern District";
string documentType = "Motion for Summary Judgment";
string filingParty = "Plaintiff";
// Create legal document HTML
string legalDocumentHtml = $@"
E html>
le>
body {{
font-family: 'Times New Roman', Times, serif;
font-size: 12pt;
line-height: 2;
margin: 1in;
}}
.header {{ text-align: center; margin-bottom: 24pt; }}
.case-caption {{
border: 1px solid black;
padding: 12pt;
margin: 24pt 0;
}}
.section {{ margin: 12pt 0; }}
h1 {{ font-size: 14pt; text-align: center; }}
.signature {{ margin-top: 48pt; }}
yle>
class='header'>
<strong>{courtName}</strong>
v>
class='case-caption'>
<p>ACME CORPORATION,<br> Plaintiff,</p>
<p>v.</p>
<p>EXAMPLE INDUSTRIES, INC.,<br> Defendant.</p>
<p style='text-align: right;'><strong>Case No. {caseNumber}</strong></p>
v>
{documentType.ToUpper()}</h1>
class='section'>
<p>Plaintiff ACME Corporation, by and through undersigned counsel, respectfully
moves this Court for summary judgment pursuant to Federal Rule of Civil Procedure 56...</p>
v>
class='section'>
<h2>I. INTRODUCTION</h2>
<p>This motion presents the Court with a straightforward question of contract interpretation...</p>
v>
class='signature'>
<p>Respectfully submitted,</p>
<p>_________________________<br>
Jane Attorney, Esq.<br>
Bar No. 12345<br>
Law Firm LLP<br>
123 Legal Street<br>
City, State 12345<br>
(555) 123-4567<br>
jane@lawfirm.com</p>
<p>Attorney for Plaintiff</p>
v>
;
// Render with court-appropriate settings
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.Letter;
renderer.RenderingOptions.MarginTop = 72;
renderer.RenderingOptions.MarginBottom = 72;
renderer.RenderingOptions.MarginLeft = 72;
renderer.RenderingOptions.MarginRight = 72;
using var pdf = renderer.RenderHtmlAsPdf(legalDocumentHtml);
// Set metadata for court filing system indexing
var metadata = new System.Collections.Generic.Dictionary<string, string>
{
{ "Title", $"{documentType} - {caseNumber}" },
{ "Author", "Law Firm LLP" },
{ "Subject", $"Court Filing - {caseNumber}" },
{ "CaseNumber", caseNumber },
{ "DocumentType", documentType },
{ "FilingParty", filingParty },
{ "FilingDate", DateTime.Now.ToString("yyyy-MM-dd") }
};
pdf.MetaData.SetMetaDataDictionary(metadata);
// Convert to PDF/A-2b (widely accepted by federal courts)
string outputPath = $"court-filing-{caseNumber.Replace(":", "-")}.pdf";
pdf.SaveAsPdfA(outputPath, PdfAVersions.PdfA2b);
Imports IronPdf
Imports System
Imports System.Collections.Generic
' Court filing configuration
Dim caseNumber As String = "1:26-cv-00142-ABC"
Dim courtName As String = "US District Court, Northern District"
Dim documentType As String = "Motion for Summary Judgment"
Dim filingParty As String = "Plaintiff"
' Create legal document HTML
Dim legalDocumentHtml As String = $"
<!DOCTYPE html>
<html>
<head>
<style>
body {{
font-family: 'Times New Roman', Times, serif;
font-size: 12pt;
line-height: 2;
margin: 1in;
}}
.header {{ text-align: center; margin-bottom: 24pt; }}
.case-caption {{
border: 1px solid black;
padding: 12pt;
margin: 24pt 0;
}}
.section {{ margin: 12pt 0; }}
h1 {{ font-size: 14pt; text-align: center; }}
.signature {{ margin-top: 48pt; }}
</style>
</head>
<body>
<div class='header'>
<strong>{courtName}</strong>
</div>
<div class='case-caption'>
<p>ACME CORPORATION,<br> Plaintiff,</p>
<p>v.</p>
<p>EXAMPLE INDUSTRIES, INC.,<br> Defendant.</p>
<p style='text-align: right;'><strong>Case No. {caseNumber}</strong></p>
</div>
<h1>{documentType.ToUpper()}</h1>
<div class='section'>
<p>Plaintiff ACME Corporation, by and through undersigned counsel, respectfully
moves this Court for summary judgment pursuant to Federal Rule of Civil Procedure 56...</p>
</div>
<div class='section'>
<h2>I. INTRODUCTION</h2>
<p>This motion presents the Court with a straightforward question of contract interpretation...</p>
</div>
<div class='signature'>
<p>Respectfully submitted,</p>
<p>_________________________<br>
Jane Attorney, Esq.<br>
Bar No. 12345<br>
Law Firm LLP<br>
123 Legal Street<br>
City, State 12345<br>
(555) 123-4567<br>
jane@lawfirm.com</p>
<p>Attorney for Plaintiff</p>
</div>
</body>
</html>
"
' Render with court-appropriate settings
Dim renderer As New ChromePdfRenderer()
renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.Letter
renderer.RenderingOptions.MarginTop = 72
renderer.RenderingOptions.MarginBottom = 72
renderer.RenderingOptions.MarginLeft = 72
renderer.RenderingOptions.MarginRight = 72
Using pdf = renderer.RenderHtmlAsPdf(legalDocumentHtml)
' Set metadata for court filing system indexing
Dim metadata As New Dictionary(Of String, String) From {
{"Title", $"{documentType} - {caseNumber}"},
{"Author", "Law Firm LLP"},
{"Subject", $"Court Filing - {caseNumber}"},
{"CaseNumber", caseNumber},
{"DocumentType", documentType},
{"FilingParty", filingParty},
{"FilingDate", DateTime.Now.ToString("yyyy-MM-dd")}
}
pdf.MetaData.SetMetaDataDictionary(metadata)
' Convert to PDF/A-2b (widely accepted by federal courts)
Dim outputPath As String = $"court-filing-{caseNumber.Replace(":", "-")}.pdf"
pdf.SaveAsPdfA(outputPath, PdfAVersions.PdfA2b)
End Using
輸出
對於正在建置文件管理系統的律師事務所及法律科技公司而言,將 PDF/A 轉換整合至歸檔工作流程中,可確保每份歸檔文件皆符合法院的長期保存要求——且無需法律助理或律師的手動介入。
醫療紀錄保存
醫療機構在保存病患紀錄方面面臨嚴格的要求。 雖然《健康保險流通與責任法案》(HIPAA)並未強制規定特定檔案格式,但考量到漫長的保存期限(成人通常為 7 至 10 年,未成年人則更長)、無障礙存取要求以及稽核期望,PDF/A 自然成為歸檔醫療文件的理想選擇。
醫療紀錄歸檔的關鍵考量:
保存期限 — 聯邦及州法規要求醫療紀錄須保存不同長度的期限,通常長達 10 年以上。 PDF/A 格式能確保長期可讀性,使其成為滿足這些需求的理想選擇,無需擔心格式過時的問題。
無障礙性 — 《美國殘疾人法案》(ADA)及《第 508 條》規定,電子病歷必須具備無障礙性。 使用 PDF/A-2a 或 PDF/A-3a 合規等級(包含結構標記)有助於滿足這些無障礙要求。
互通性 — 醫療紀錄經常在醫療服務提供者、保險公司與患者之間共享。 PDF/A 的自包含特性確保文件無論使用何種檢視器或系統開啟,皆能一致地呈現。
稽核準備 — 醫療稽核可能要求在醫療紀錄建立數年後仍須提供該紀錄。 PDF/A 可確保審計過程中產生的文件與原始文件完全一致,不會出現任何可能引發文件完整性質疑的渲染差異。
:path=/static-assets/pdf/content-code-examples/tutorials/pdfa-archiving-csharp/pdfa-medical-records.cs
using IronPdf;
using System;
using System.Collections.Generic;
// Medical record metadata
string patientId = "MRN-2026-00847";
string documentType = "Discharge Summary";
string facility = "Metro General Hospital";
string department = "Internal Medicine";
DateTime encounterDate = new DateTime(2026, 2, 5);
// Create clinical document HTML
string clinicalDocumentHtml = $@"
E html>
ng='en'>
le>
body {{ font-family: Arial, sans-serif; margin: 40px; line-height: 1.6; }}
.header {{ border-bottom: 2px solid #2c3e50; padding-bottom: 15px; margin-bottom: 20px; }}
.patient-info {{ background: #ecf0f1; padding: 15px; margin: 15px 0; }}
.section {{ margin: 20px 0; }}
h1 {{ color: #2c3e50; }}
h2 {{ color: #3498db; font-size: 14pt; }}
.footer {{ margin-top: 40px; font-size: 10pt; color: #666; }}
yle>
class='header'>
<h1>{facility}</h1>
<p>{department} | {documentType}</p>
v>
class='patient-info'>
<p><strong>Patient ID:</strong> {patientId}</p>
<p><strong>Encounter Date:</strong> {encounterDate:MMMM d, yyyy}</p>
<p><strong>Attending Physician:</strong> Dr. Sarah Johnson, MD</p>
v>
class='section'>
<h2>Chief Complaint</h2>
<p>Patient presented with acute respiratory symptoms including shortness of breath and persistent cough.</p>
v>
class='section'>
<h2>Hospital Course</h2>
<p>Patient was admitted for observation and treatment. Symptoms improved with standard protocol...</p>
v>
class='section'>
<h2>Discharge Instructions</h2>
<ul>
<li>Continue prescribed medications as directed</li>
<li>Follow up with primary care physician within 7 days</li>
<li>Return to ED if symptoms worsen</li>
</ul>
v>
class='footer'>
<p>Document generated: {DateTime.Now:yyyy-MM-dd HH:mm}</p>
<p>This document is archived in PDF/A-3a format for accessibility and long-term preservation.</p>
v>
;
var renderer = new ChromePdfRenderer();
using var pdf = renderer.RenderHtmlAsPdf(clinicalDocumentHtml);
// Set comprehensive metadata for medical records management
var metadata = new System.Collections.Generic.Dictionary<string, string>
{
{ "Title", $"{documentType} - {patientId}" },
{ "Author", "Metro General Hospital EHR System" },
{ "Subject", $"Clinical documentation for patient {patientId}" },
{ "PatientMRN", patientId },
{ "DocumentType", documentType },
{ "Facility", facility },
{ "Department", department },
{ "EncounterDate", encounterDate.ToString("yyyy-MM-dd") },
{ "RetentionCategory", "Medical Record - Adult" },
{ "RetentionPeriod", "10 years from last encounter" }
};
pdf.MetaData.SetMetaDataDictionary(metadata);
// Embed clinical data (HL7 FHIR format)
string fhirData = @"{
sourceType"": ""DocumentReference"",
atus"": ""current"",
pe"": { ""text"": ""Discharge Summary"" },
bject"": { ""reference"": ""Patient/MRN-2026-00847"" }
byte[] fhirBytes = System.Text.Encoding.UTF8.GetBytes(fhirData);
var fhirConfig = new EmbedFileConfiguration(EmbedFileType.xml)
{
EmbedFileName = "clinical-data.json",
AFDesc = "FHIR DocumentReference metadata",
AFRelationship = AFRelationship.Data
};
var embedFiles = new List<EmbedFileByte>
{
new EmbedFileByte(fhirBytes, fhirConfig)
};
// Convert to PDF/A-3a (accessible archival with embedded data)
using var archivedRecord = pdf.ConvertToPdfA(embedFiles, PdfAVersions.PdfA3a);
string outputPath = $"medical-record-{patientId}-{encounterDate:yyyyMMdd}.pdf";
archivedRecord.SaveAs(outputPath);
Imports IronPdf
Imports System
Imports System.Collections.Generic
Imports System.Text
' Medical record metadata
Dim patientId As String = "MRN-2026-00847"
Dim documentType As String = "Discharge Summary"
Dim facility As String = "Metro General Hospital"
Dim department As String = "Internal Medicine"
Dim encounterDate As DateTime = New DateTime(2026, 2, 5)
' Create clinical document HTML
Dim clinicalDocumentHtml As String = $"
<!DOCTYPE html>
<html lang='en'>
<head>
<style>
body {{ font-family: Arial, sans-serif; margin: 40px; line-height: 1.6; }}
.header {{ border-bottom: 2px solid #2c3e50; padding-bottom: 15px; margin-bottom: 20px; }}
.patient-info {{ background: #ecf0f1; padding: 15px; margin: 15px 0; }}
.section {{ margin: 20px 0; }}
h1 {{ color: #2c3e50; }}
h2 {{ color: #3498db; font-size: 14pt; }}
.footer {{ margin-top: 40px; font-size: 10pt; color: #666; }}
</style>
</head>
<body>
<div class='header'>
<h1>{facility}</h1>
<p>{department} | {documentType}</p>
</div>
<div class='patient-info'>
<p><strong>Patient ID:</strong> {patientId}</p>
<p><strong>Encounter Date:</strong> {encounterDate:MMMM d, yyyy}</p>
<p><strong>Attending Physician:</strong> Dr. Sarah Johnson, MD</p>
</div>
<div class='section'>
<h2>Chief Complaint</h2>
<p>Patient presented with acute respiratory symptoms including shortness of breath and persistent cough.</p>
</div>
<div class='section'>
<h2>Hospital Course</h2>
<p>Patient was admitted for observation and treatment. Symptoms improved with standard protocol...</p>
</div>
<div class='section'>
<h2>Discharge Instructions</h2>
<ul>
<li>Continue prescribed medications as directed</li>
<li>Follow up with primary care physician within 7 days</li>
<li>Return to ED if symptoms worsen</li>
</ul>
</div>
<div class='footer'>
<p>Document generated: {DateTime.Now:yyyy-MM-dd HH:mm}</p>
<p>This document is archived in PDF/A-3a format for accessibility and long-term preservation.</p>
</div>
</body>
</html>"
Dim renderer As New ChromePdfRenderer()
Using pdf = renderer.RenderHtmlAsPdf(clinicalDocumentHtml)
' Set comprehensive metadata for medical records management
Dim metadata As New Dictionary(Of String, String) From {
{"Title", $"{documentType} - {patientId}"},
{"Author", "Metro General Hospital EHR System"},
{"Subject", $"Clinical documentation for patient {patientId}"},
{"PatientMRN", patientId},
{"DocumentType", documentType},
{"Facility", facility},
{"Department", department},
{"EncounterDate", encounterDate.ToString("yyyy-MM-dd")},
{"RetentionCategory", "Medical Record - Adult"},
{"RetentionPeriod", "10 years from last encounter"}
}
pdf.MetaData.SetMetaDataDictionary(metadata)
' Embed clinical data (HL7 FHIR format)
Dim fhirData As String = "{
""resourceType"": ""DocumentReference"",
""status"": ""current"",
""type"": { ""text"": ""Discharge Summary"" },
""subject"": { ""reference"": ""Patient/MRN-2026-00847"" }
}"
Dim fhirBytes As Byte() = Encoding.UTF8.GetBytes(fhirData)
Dim fhirConfig As New EmbedFileConfiguration(EmbedFileType.xml) With {
.EmbedFileName = "clinical-data.json",
.AFDesc = "FHIR DocumentReference metadata",
.AFRelationship = AFRelationship.Data
}
Dim embedFiles As New List(Of EmbedFileByte) From {
New EmbedFileByte(fhirBytes, fhirConfig)
}
' Convert to PDF/A-3a (accessible archival with embedded data)
Using archivedRecord = pdf.ConvertToPdfA(embedFiles, PdfAVersions.PdfA3a)
Dim outputPath As String = $"medical-record-{patientId}-{encounterDate:yyyyMMdd}.pdf"
archivedRecord.SaveAs(outputPath)
End Using
End Using
輸出
對於電子健康紀錄(EHR)系統而言,最有效的方法是在文件生成之際(例如實驗室報告產生、臨床筆記定稿或出院摘要製作時)將文件轉換為 PDF/A 格式。 這種"建立時即歸檔"的策略,可避免日後進行批次遷移所產生的成本與複雜性。
後續步驟
將文件歸檔為 PDF/A 格式,其實並不複雜。 IronPDF for .NET 提供一套完整的工具組,可在熟悉的 C# 生態系統中,創建、轉換及增強符合 PDF/A 標準的文件。 無論您是從 HTML 生成歸檔文件、製作供政府及醫療機構分發的無障礙 PDF、轉換舊版 PDF 以供長期儲存,還是將外部驗證整合至高量批處理流程中,IronPDF 都會處理技術細節,讓您能專注於應用程式的需求。
從基礎的 PDF/A-1 標準到 PDF/A-3 和 PDF/A-4 的現代功能,IronPDF 支援完整的歸檔版本與合規等級——包括 PDF/A-4e 以及 PDF/A-4f。 專用的 PDF/A 操作指南詳細說明了轉換選項與合規等級。 結合元資料管理、透過 EmbedFileConfiguration 嵌入檔案,以及對 ZUGFeRD/Factur-X 電子發票的支援,它提供了您所需的一切,以滿足政府機關、法院系統、醫療機構及金融機構的歸檔要求。
準備開始歸檔了嗎? 下載 IronPDF 並透過免費試用版體驗其功能。 如有疑問或希望討論您的特定合規情境,請聯繫我們的工程支援團隊——我們很樂意協助您正確處理。
常見問題
何謂 PDF/A 合規性?
PDF/A 合規性指的是專為電子文件的歸檔與長期保存而設計的 ISO 標準化 PDF 版本。它確保文件在未來數年內能以相同的方式重現。
如何使用 C# 建立符合 PDF/A 標準的文件?
您可以透過 C# 並利用 IronPDF 函式庫來建立符合 PDF/A 標準的文件,該函式庫提供強大的工具,可產生並將 PDF 轉換為各種 PDF/A 格式。
IronPDF 支援哪些不同的 PDF/A 版本?
IronPDF 支援多種 PDF/A 版本,包括 PDF/A-1、PDF/A-2 及 PDF/A-3,各版本皆能滿足文件歸檔與保存的不同需求。
IronPDF 能否協助嵌入符合 ZUGFeRD 和 Factur-X 等電子發票標準的原始資料?
是的,IronPDF 可以嵌入 ZUGFeRD 和 Factur-X 等電子發票標準的原始資料,以協助電子發票的處理與合規。
如何在 C# 中驗證 PDF/A 合規性?
您可以透過 C# 中的 IronPDF,利用其內建的驗證工具來驗證 PDF/A 合規性,以確保您的文件符合所需的 PDF/A 規格。
IronPDF 能否處理政府檔案歸檔的情境?
是的,IronPDF 能夠處理各種政府檔案歸檔情境,包括符合 NARA 標準、法院文件及醫療紀錄所需的規範。
using PDF/A 進行歸檔有哪些好處?
using PDF/A 進行歸檔的優勢包括:確保文件隨時間推移仍能保持原貌、提供長期保存的標準化格式,以及符合法律與組織規範。
IronPDF 是否支援將現有 PDF 檔案轉換為 PDF/A 格式?
IronPDF 支援將現有 PDF 檔案轉換為 PDF/A 格式,有助於輕鬆符合規範並實現文件的長期保存。
IronPDF 如何確保 PDF/A 轉換過程中的文件忠實度?
IronPDF 透過維持字型、圖片及版面配置的完整性,確保 PDF/A 轉換過程中的文件忠實度,使歸檔後的文件呈現效果完全符合預期。
我可以使用 IronPDF 來歸檔醫療紀錄嗎?
是的,IronPDF 可用於醫療紀錄歸檔,有助於確保符合文件保存的產業標準與法規。

