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

將 PDF 轉換為 PDF/A

本文說明如何使用 Docotic.Pdf 將 PDF 文件轉換為 PDF/A。這個 .NET 函式庫包含一個高效能的 PDF 轉 PDF/A 轉換器,可完全離線執行。你也可以使用 Docotic.Pdf 從頭建立 PDF/A 文件。

PDF 轉 PDF/A

為什麼要將 PDF 轉換為 PDF/A?

PDF/A 是專為長期封存設計的特殊 PDF 版本。將標準 PDF 文件轉換為 PDF/A 具有多項優點:

  1. 長期保存
    PDF/A 文件可在多年後仍保持可存取與可使用,因此非常適合法律、政府與歸檔用途。

  2. 符合法規要求
    對合規與法律要求嚴格的產業,常會以 PDF/A 格式儲存文件。

  3. 在不同 PDF 檢視器中外觀一致
    PDF/A 文件在不同系統與不同 PDF 檢視器中都能一致顯示。

請閱讀 什麼是 PDF/A? 文章,以進一步了解 PDF/A 標準。

在 C# 中將 PDF 轉換為 PDF/A

若要將 PDF 轉換為 PDF/A,你需要:

  1. 安裝含有 Conformance 附加元件 的 Docotic.Pdf。
  2. 一個授權金鑰。你可以從 下載頁面 取得免費的限時授權。

以下 C# 程式碼會將 PDF 檔案轉換為 PDF/A-4:

using var pdf = new PdfDocument("input.pdf");
pdf.SaveAsPdfa("output.pdf", PdfaConformanceLevel.Pdfa4);

SaveAsPdfa 方法由 BitMiracle.Docotic.Pdf.Conformance 命名空間中的附加元件提供。它支援所有 PDF/A 相容等級:PDF/A-1a、PDF/A-1b、PDF/A-2a、PDF/A-2b、PDF/A-2u、PDF/A-3a、PDF/A-3b、PDF/A-3u、PDF/A-4、PDF/A-4e、PDF/A-4f。輸出可寫入檔案或串流。

如果來源文件無法轉換為要求的 PDF/A 相容等級,SaveAsPdfa 會擲回 ConformanceException。詳情請參閱 錯誤處理 一節。

進階場景

Docotic.Pdf 支援廣泛的 PDF/A 工作流程,包括從頭建立 PDF/A 文件、將 HTML 轉換為 PDF/A,以及將文件合併為單一 PDF/A 檔案。

建立 PDF/A 文件

Docotic.Pdf 提供不同方式來 在 .NET 中建立 PDF 文件。你可以使用相同的 SaveAsPdfa 方法,透過 Core API 或 Layout API 產生 PDF/A 文件。

以下 C# 程式碼使用 Core API 建立一份 PDF/A-3u 文件:

using var pdf = new PdfDocument();
pdf.Pages[0].Canvas.DrawString("Hello PDF/A");
pdf.SaveAsPdfa("output.pdf", PdfaConformanceLevel.Pdfa3U);

使用 Layout API,你先建立一般 PDF 文件,再將其轉換為 PDF/A。此程式碼範例示範如何產生 PDF/A-1b 文件:

using var ms = new MemoryStream();
PdfDocumentBuilder.Create().Generate(ms, doc => doc.Pages(pages =>
{
    pages.Content().Text("Hello, world!");
}));

using var pdf = new PdfDocument(ms);
pdf.SaveAsPdfa("output.pdf", PdfaConformanceLevel.Pdfa1B);

HTML 轉換為 PDF/A

HtmlToPdf 附加元件會將 HTML 轉換為 PDF。若要讓結果適合封存,請將產生的 PDF 另存為 PDF/A:

var uri = new Uri("https://google.com");
var options = new HtmlConversionOptions
{
    PreserveStructureInformation = true,
};

using var converter = await HtmlConverter.CreateAsync();
using var pdf = await converter.CreatePdfAsync(uri, options);
pdf.SaveAsPdfa("output.pdf", PdfaConformanceLevel.Pdfa3A);

PreserveStructureInformation = true 選項有助於產生可存取文件。這對 PDF/A-1a、PDF/A-2a 或 PDF/A-3a 相容等級很重要。

將 PDF 文件合併為 PDF/A

Docotic.Pdf 支援 合併 PDF 文件。將 PdfDocument.Save 呼叫改為 SaveAsPdfa,即可將合併後的文件儲存為 PDF/A:

using var pdf = new PdfDocument("first.pdf");
pdf.Append("second.pdf");
pdf.SaveAsPdfa("merged.pdf", PdfaConformanceLevel.Pdfa1B);

你也可以在其他 PDF 編輯 情境中套用相同原則。例如,刪除 PDF 頁面、編輯文字、扁平化表單欄位,最後另存為 PDF/A。

在 C# 中建立 ZUGFeRD / Factur-X 檔案

Factur-X / ZUGFeRD 是一種基於 PDF/A-3 的歐洲電子發票標準。你可以使用 Docotic.Pdf 嵌入 XML 發票檔案,並產生有效的 Factur-X / ZUGFeRD 文件:

using var pdf = new PdfDocument();

PdfFileSpecification xml = pdf.CreateFileAttachment("your_path_to/xrechnung.xml");
xml.Relationship = "Alternative";
pdf.SharedAttachments.Add(xml);

var fx = new XmpSchema("fx", "urn:factur-x:pdfa:CrossIndustryDocument:invoice:1p0#");
var props = fx.Properties;
props.Add(new XmpProperty("DocumentType", new XmpString("INVOICE")));
props.Add(new XmpProperty("DocumentFileName", new XmpString("xrechnung.xml")));
props.Add(new XmpProperty("Version", new XmpString("3.0")));
props.Add(new XmpProperty("ConformanceLevel", new XmpString("XRECHNUNG")));

pdf.Metadata.Schemas.Add(fx);

pdf.SaveAsPdfa("zugferd.pdf", PdfaConformanceLevel.Pdfa3A);

建立 Order-X 文件

Order-X 是另一項 EU 標準,允許對採購訂單進行電子處理。以下 C# 程式碼片段示範如何使用 COMFORT 設定檔建立 Order-X 文件:

using var pdf = new PdfDocument();

using (var file = File.OpenRead("order-data-comfort.xml"))
{
    PdfFileSpecification xml = pdf.CreateFileAttachment(file, "order-x.xml");
    xml.Relationship = "Data";
    pdf.SharedAttachments.Add(xml);
}

var fx = new XmpSchema("fx", "urn:factur-x:pdfa:CrossIndustryDocument:1p0#");
var props = fx.Properties;
props.Add(new XmpProperty("DocumentType", new XmpString("ORDER")));
props.Add(new XmpProperty("DocumentFileName", new XmpString("order-x.xml")));
props.Add(new XmpProperty("Version", new XmpString("1.0")));
props.Add(new XmpProperty("ConformanceLevel", new XmpString("COMFORT")));

pdf.Metadata.Schemas.Add(fx);

pdf.SaveAsPdfa("order-x.pdf", PdfaConformanceLevel.Pdfa3B);

將受保護的 PDF 檔案轉換為 PDF/A

加密 PDF 檔案的轉換沒有不同。只要 使用正確密碼開啟文件 並呼叫 SaveAsPdfa

using var pdf = new PdfDocument(fileName, new PdfStandardDecryptionHandler("password"));
pdf.SaveAsPdfa("result.pdf", PdfaConformanceLevel.Pdfa4E);

批次處理

你可以自動化多個 PDF 檔案轉換為 PDF/A 的流程。列出目錄中的所有 PDF 檔案,並將每份文件轉換為 PDF/A。以下程式碼範例示範如何平行轉換檔案:

public static async Task ConvertAsync(string directoryPath)
{
    string[] files = Directory.GetFiles(directoryPath, "*.pdf", SearchOption.AllDirectories);
    if (files.Length == 0)
        return;

    var semaphore = new SemaphoreSlim(Environment.ProcessorCount);
    var tasks = new List<Task>(files.Length);
    foreach (var f in files)
    {
        await semaphore.WaitAsync();

        var task = Task.Run(() =>
        {
            string outputFileName = $"{Path.GetFileName(f)}-{Guid.NewGuid()}.pdf";
            try
            {
                using var pdf = new PdfDocument(f);
                pdf.SaveAsPdfa(outputFileName, PdfaConformanceLevel.Pdfa1B);
            }
            finally
            {
                semaphore.Release();
            }
        });

        tasks.Add(task);
    }

    await Task.WhenAll(tasks);
}

當你為任意 PDF 檔案實作轉換工作流程時,值得驗證所有產生的檔案是否符合 PDF/A。你可以在 評估轉換品質 一節找到可直接使用的批次轉換與驗證應用程式。

錯誤處理

在某些情況下轉換可能失敗。例如,當:

  • 輸入檔不是 PDF
  • 對加密的 PDF 提供了無效密碼
  • 無法為 PDF/A 嵌入字型位元組

在這些情況下,Docotic.Pdf 會擲回例外。以下範例程式碼示範如何處理例外:

try
{
    using var pdf = new PdfDocument("input.pdf");
    pdf.SaveAsPdfa("output.pdf", PdfaConformanceLevel.Pdfa1B);
}
catch (PdfException ex)
{
    Console.WriteLine($"Problem with an input document: {ex.Message}");
}
catch (ConformanceException ex)
{
    Console.WriteLine($"Unable to convert to PDF/A: {ex.Message}");
}

從 PDF/A 轉換為 PDF

將 PDF/A 轉換為 PDF,有時可讓文件更容易編輯。這個流程比 PDF 轉 PDF/A 簡單得多。你只需要移除一部分 XMP 中繼資料。範例程式碼:

using var pdf = new PdfDocument("pdfa-compliant.pdf");

var schemas = pdf.Metadata.Schemas;
for (int i = 0; i < schemas.Count; ++i)
{
    if (schemas[i].Namespace == "http://www.aiim.org/pdfa/ns/id/")
    {
        schemas.RemoveAt(i);
        --i;
    }
}

pdf.Save("regular.pdf");

為什麼選擇 Docotic.Pdf 作為 PDF 轉 PDF/A 轉換方案?

Docotic.Pdf 是一個高效能、純 C# .NET 的函式庫,不依賴外部元件。你可以用它在 Windows、Linux、macOS、Android、iOS 或雲端環境中產生 PDF/A 文件。此外,Docotic.Pdf 還提供以下優點:

獨立離線轉換

轉換完全在你的電腦上進行。沒有任何資料會傳送到外部伺服器或第三方供應商。離線轉換有助於保護敏感文件,因為資料不會離開你的環境。

品質

Docotic.Pdf 設計為在轉換過程中盡可能保留原始資訊,同時不犧牲品質。

ISO 相容性

Docotic.Pdf 產生的 PDF/A 檔案符合以下 ISO 標準:

  • ISO 19005-1:2005 (PDF/A-1)
  • ISO 19005-2:2011 (PDF/A-2)
  • ISO 19005-3:2012 (PDF/A-3)
  • ISO 19005-4:2020 (PDF/A-4)

每個 Docotic.Pdf 建置版本都會通過數千項自動化測試。PDF 轉 PDF/A 測試使用來自不同來源的大量 PDF 檔案,並將它們轉換為各種 PDF/A 相容等級。接著再驗證產生的檔案是否符合 PDF/A。

其中一組測試會檢查 veraPDF 是否對轉換後的檔案報告任何問題。另一組測試會 將每個結果檔案 與其預期的 PDF/A 版本進行比較;該版本已由 veraPDF 與 Adobe Acrobat Preflight 驗證不含任何相容性問題。

評估轉換品質

我們提供開源 PdfToPdfa 專案。這是一個 .NET 主控台應用程式,可將 PDF 檔案轉換為 PDF/A。轉換後,應用程式會驗證每份結果文件。該專案使用 Docotic.Pdf 進行轉換,並使用 veraPDF 進行驗證。

你可以用命令列模式使用這個應用程式,自動化你的 PDF/A 工作流程。也可以用 UI 模式快速評估轉換品質與效能。

將 PDF 檔案轉換為 PDF/A 並驗證 PDF/A 相容性

此應用程式可處理任意 PDF 檔案或目錄。為方便使用,專案存放庫也包含來自 veraPDF corpus 與 Isartor Test Suite 的測試檔案。

在轉換為 PDF/A 的過程中會發生什麼事?

PDF/A 規範定義了相容文件的大量 要求。轉換器會驗證並強制套用這些要求,以產生有效的 PDF/A 檔案。從高層次來看,它會檢查每個 PDF 物件,並修正偵測到的 PDF/A 相容性問題。

並非所有 PDF 都能在不改變內容的情況下轉換為 PDF/A。某些 PDF 功能會被所選的 PDF/A 相容等級禁止,因此轉換器必須移除或轉換它們。因此,轉換可能是一個有損過程。

例如,PDF/A-1 不允許可選內容(圖層)、嵌入檔案(附件)或透明度。如果原始 PDF 文件使用了這些功能,轉換器會扁平化圖層、移除附件與透明度。若保留這類內容很重要,請選擇支援它的 PDF/A 相容等級:

  • 所有 PDF/A-2、PDF/A-3 與 PDF/A-4 相容等級都支援透明度與可選內容。
  • PDF/A-3、PDF/A-4 與 PDF/A-4f 支援任意嵌入檔案。PDF/A-2 與 PDF/A-4 只支援嵌入的 PDF/A 檔案。

讓我們看看 Docotic.Pdf 如何修正最常見的問題。

字型與文字

轉換器會嘗試嵌入文件中使用的每一種字型。對於尚未嵌入的字型,它會先嘗試從系統字型集合或自訂字型來源載入對應的字型資料。如果找不到相符字型,就會使用替代字型。

你可以透過提供自訂字型載入器來自訂這個流程。IFontLoader 介面用於載入字型資料。例如,DirectoryFontLoader 實作會從一個或多個指定目錄載入字型位元組。

IFontLoader 無法載入要求的字型時,你也可以提供 IFallbackFontProvider 介面的實作,以提供替代字型。

以下範例示範如何自訂字型載入:

public static void ConfigurePdfToPdfa(
    string fileName,
    PdfaConformanceLevel level,
    Stream output,
    IFontLoader? fontLoader,
    IFallbackFontProvider? fallbackFontProvider)
{
    var config = PdfConfigurationOptions.Create();
    if (fontLoader != null)
        config.FontLoader = fontLoader;

    if (fallbackFontProvider != null)
        config.FallbackFontProvider = fallbackFontProvider;

    using var pdf = new PdfDocument(fileName, config);
    pdf.SaveAsPdfa(output, level);
}

Docotic.Pdf 也會修正不一致的字形寬度、CMap 與 ToUnicode 串流。未定義字元會在轉換過程中移除。

中繼資料

轉換器會修正或移除無效的中繼資料綱要或屬性,加入 pdfaid 綱要,並同步 XMP 中繼資料與文件資訊字典。

Conformance 附加元件也提供 PdfDocumentReadPdfaConformance 擴充方法。使用此方法可讀取在 XMP 中繼資料中宣告的 PDF/A 相容等級:

using var pdf = new PdfDocument("input.pdf");
PdfaConformanceLevel? level = pdf.ReadPdfaConformance();

色彩

由於 PDF/A 文件不允許裝置相依色彩,轉換器會為裝置色彩提供輸出意圖 ICC 配置檔。它也會修正不相容的輸出意圖與色彩空間。

產生 PDF/A-1 文件時會移除透明度。這會影響混合模式、軟遮罩與透明度群組。無效的影像屬性也會被修正。

嵌入檔案

對嵌入檔案的處理取決於 PDF/A 相容等級。在 PDF/A-1 中,所有嵌入檔案都會被移除。

在 PDF/A-2 與 PDF/A-4 中,嵌入的 PDF 檔案會轉換為 PDF/A。非 PDF 附件會被移除。對於嵌入的 PDF/A 檔案,PDF/A-4 也會修正 MIME 類型與檔案關係。

在 PDF/A-3 中,附件不會被移除,但會修正檔案關係與 MIME 類型。

互動功能

轉換器會產生缺少或無效的外觀串流。它也會修正無效的註解屬性、扁平化不允許類型的註解,並移除不允許類型的動作。

PDF/A-2、PDF/A-3 與 PDF/A-4 會移除 XFA 表單。只有 PDF/A-1 允許 XFA 表單,但它們仍不建議用於長期封存。

當目標為 PDF/A-1 時,可選內容會被扁平化。對於其他相容等級,轉換器會修正可選內容設定字典中不完整的順序陣列、缺失名稱或重複名稱。

數位簽章

數位簽章 從設計上不允許修改已簽署內容。如果 PDF 的已簽署部分包含 PDF/A 相容性問題,轉換器會修正它們並使簽章失效。

其他領域

為了無障礙性,如果文件缺少基本結構資訊,轉換器會加以補上。它也會修正無效或非標準的結構標籤。這適用於 PDF/A-1a、PDF/A-2a 與 PDF/A-3a 文件。

PDF/A 文件不得加密,因此轉換器不允許輸出檔案加密。

PDF/A 不允許使用 LZW 壓縮資料。轉換器會使用 Flate 壓縮重新壓縮 LZW 串流。它也會修正不相容的陣列、字典、數字、名稱與字串物件。

無效的檔案標頭或交叉參照區段也會自動修正。

結論

搭配 Conformance 附加元件的 Docotic.Pdf 提供高品質的 PDF 轉 PDF/A 轉換器。你可以將既有 PDF 文件轉換為任何 PDF/A 相容等級,或從頭建立 PDF/A 文件。這個函式庫完全在內部環境中運作,因此你的資料不會離開伺服器。

你可以在範例存放庫的 PDF/A 區段 中,查看可執行的 C# 與 VB.NET 範例,用於建立與處理 PDF/A 文件。

另外也有開源的 PdfToPdfa 應用程式,可用於 PDF 轉 PDF/A。你可以用它自動化 PDF/A 工作流程,或只是單純將 PDF 檔案轉換為 PDF/A。

常見問題

如何選擇正確的 PDF 轉 PDF/A 轉換器?

好的 PDF 轉 PDF/A 轉換器應該:

  1. 產生符合 PDF/A 的檔案。
  2. 保留來源文件中的資訊與視覺外觀。
  3. 可在本機執行,不將檔案傳送至第三方伺服器。
  4. 執行速度快。
  5. (若需要自動化)支援無 UI 執行。

Docotic.Pdf 函式庫符合所有條件,是將 PDF 轉換為 PDF/A 的良好選擇。

如何驗證 PDF/A 文件是否符合規範?

請使用驗證軟體。好的 PDF/A 驗證器應該:

  1. 深入遵循 PDF/A 的 ISO 標準。
  2. 可在本機執行,不將檔案傳送至第三方伺服器。
  3. 執行速度快。
  4. (若需要自動化)支援無 UI 執行。

veraPDF 是業界標準的驗證工具,支援以上所有需求。

如何自動化 PDF 轉 PDF/A 的轉換工作流程?

使用 Docotic.Pdf Conformance 附加元件轉換 PDF 檔案。使用 veraPDF 驗證器驗證結果。追蹤轉換與驗證進度。

開源 PdfToPdfa 應用程式 實作了這個工作流程。你可以將它作為自行實作的起點。

我應該使用哪個 PDF/A 版本?

請閱讀 如何選擇 PDF/A 版本 一節。

我可以將 XML 檔嵌入 PDF 以用於 ZUGFeRD 嗎?

可以,當然可以。請參考 建立 ZUGFeRD / Factur-X 檔案 一節中的範例。

如何保護 PDF/A 文件?

從技術上說這是不可能的。PDF/A 文件不得加密。