Bài viết kỹ thuật

Xuất PDF 2.0 PDF/A-4 và PDF/UA-2 với HotPDF trong Delphi

HotPDF ghi tài liệu PDF 2.0 bản địa từ Delphi và C++Builder, bao gồm ba profile lưu trữ PDF/A-4 và đầu ra dễ tiếp cận PDF/UA-2 với phần tử cấu trúc mang không gian tên. Chọn chúng chỉ là việc của hai thuộc tính, nhưng các chuẩn đằng sau những thuộc tính đó thay đổi nhiều hơn con số phiên bản gợi ý: PDF/A-4 đã bỏ các chữ cái conformance mà mọi người học cùng PDF/A-2, còn PDF/UA-2 đưa vào không gian tên cấu trúc mà một tài liệu part 1 chưa từng có

Bài viết này trình bày những gì thực sự thay đổi trong file sinh ra, và những lỗi nào HotPDF biến thành một ngoại lệ tại EndDoc thay vì thành một tài liệu thất bại xác thực tại chỗ khách hàng

Nhận dạng PDF/A-4 khác part 2 và part 3 thế nào

PDF/A-4 tự nhận diện theo số part và năm hiệu đính, không có chữ cái conformance cho part cơ sở. Đặt PDFACompliance thành '4' thì HotPDF phát ra pdfaid:part=4 kèm pdfaid:rev=2020 và hoàn toàn không có mục pdfaid:conformance nào. Chữ cái không phải bị mất — part 4 không có mức A/B/U, vì các yêu cầu từng phân biệt chúng đã được gộp vào part cơ sở

Hai phần mở rộng vẫn giữ một chữ cái. '4E' chọn PDF/A-4e cho tài liệu kỹ thuật và phát ra conformance E, vốn cho phép các đường dẫn chú thích 3D và RichMedia mà các profile khác cấm. '4F' chọn PDF/A-4f và phát ra conformance F, vốn cho phép một tệp nhúng với định dạng bất kỳ. Cả ba đều ép header PDF 2.0, yêu cầu các phép kiểm tra output intent và siêu dữ liệu PDF/A thường thấy, và cấm mã hóa — một tệp lưu trữ mã hóa là một mâu thuẫn mà chuẩn không hề dung thứ

var
  Pdf: THotPDF;
begin
  Pdf := THotPDF.Create(nil);
  try
    Pdf.FileName := 'invoice-archive.pdf';
    Pdf.PDFACompliance := '4F';   // PDF/A-4f: associated files of any format
    Pdf.BeginDoc;
    Pdf.CurrentPage.SetFont('Arial', [], 11);
    Pdf.CurrentPage.TextOut(50, 760, 0, 'Invoice 2026-0731');
    Pdf.AddPDFAssociatedFile('invoice.xml', 'text/xml',
      'Structured invoice data', 'Data', LoadInvoiceBytes);
    Pdf.EndDoc;
  finally
    Pdf.Free;
  end;
end;

AddPDFAssociatedFile nhúng tệp, dựng FileSpec của nó với một /AFRelationship, và đăng ký nó cả trong mảng /AF của Catalog lẫn cây tên EmbeddedFiles. Cả hai đăng ký đều bắt buộc; một tệp chỉ liệt kê ở một trong hai là lý do phổ biến nhất khiến một hóa đơn hybrid vượt qua kiểm tra nhanh bằng mắt và thất bại với một trình xác thực thật. Chuỗi quan hệ chấp nhận Source, Data, Alternative, Supplement hoặc Unspecified, còn profile đang hoạt động phải là PDF/A-3, PDF/A-4e hoặc PDF/A-4f — profile part 4 cơ sở không chấp nhận associated file. Tên cũ AddPDFA3AssociatedFile vẫn hoạt động cho mã sẵn có

Những gì PDF/UA-2 đòi hỏi mà PDF/UA-1 không

PDF/UA-2 ép PDF 2.0 và phát ra pdfuaid:part=2 kèm pdfuaid:rev=2024, đồng thời đưa không gian tên vào cây cấu trúc. Một tài liệu part 1 có một bộ từ vựng vai trò chuẩn phẳng. Một tài liệu part 2 có thể mang các vai trò tùy chỉnh miễn là mỗi vai trò thuộc về một không gian tên đã khai báo, và đó là điều khiến gắn thẻ chuyên đề trở nên dễ đọc với công nghệ hỗ trợ thay vì là phép đoán

Hai phương thức hiện thực điều này. RegisterStructureNamespace tạo hoặc tái sử dụng một dictionary gián tiếp /Type /Namespace và liệt kê nó trong StructTreeRoot /Namespaces, trả về dictionary để bạn tái sử dụng. AddStructureElementNS tạo một phần tử cấu trúc mà mục /NS của nó trỏ tới dictionary đó, đó là điều cấp phép cho một tên vai trò nằm ngoài bộ chuẩn. Các lệnh gọi lặp lại với cùng URI tái sử dụng một dictionary thay vì chất chồng các bản trùng

var
  Root: THPDFDictionaryObject;
begin
  Pdf.PDFUACompliance := True;
  Pdf.PDFUAPart := 2;             // part 2 forces PDF 2.0
  Pdf.Lang := 'en-US';
  Pdf.BeginDoc;
  Root := Pdf.AddStructureElement('Document', nil);
  Pdf.AddStructureElementNS('WidgetGroup',
    'https://example.com/ns/widgets', Root);
  Pdf.EndDoc;
end;

Lang không phải là trang trí ở đây. Một tài liệu đã gắn thẻ mà không khai báo ngôn ngữ tự nhiên khiến trình đọc màn hình phải đoán cách phát âm, và PDF/UA coi sự bỏ sót đó là một khiếm khuyết chứ không phải là tùy chọn

Những lỗi cấu trúc nào bị EndDoc bắt?

Bốn lỗi, mỗi lỗi tương ứng với một tài liệu mà nếu không sẽ đến tay trình xác thực trong tình trạng hỏng. Gốc cấu trúc phải chứa đúng một phần tử Document cấp cao nhất. Mọi dictionary không gian tên phải là gián tiếp, có kiểu Namespace, và mang một URI duy nhất không rỗng. Mọi tham chiếu /NS của phần tử cấu trúc phải giải tới một dictionary thực sự được liệt kê trong mảng /Namespaces của gốc. Và một vai trò không có không gian tên phải là một vai trò chuẩn PDF 2.0 hoặc giải được qua RoleMap

Những lỗi này kích hoạt tại EndDoc vì đó là khoảnh khắc cuối cùng mà toàn bộ cây tồn tại trong bộ nhớ và là khoảnh khắc đầu tiên mà cây hoàn chỉnh. Bắt chúng sớm hơn nghĩa là từ chối các trạng thái trung gian hợp lệ; bắt chúng muộn hơn nghĩa là không bắt được chúng gì cả. Hệ quả thực tế với mã của bạn là một bug cấu trúc xuất hiện cuối quá trình sinh với một thông điệp nêu tên vấn đề, thay vì xuất hiện nhiều tuần sau như một báo cáo veraPDF mà ai đó chuyển tiếp từ khách hàng

Các vai trò PDF 2.0 đáng biết

Enum vai trò có kiểu thêm vào DocumentFragment, Aside, Title, FENote, Sub, Em, StrongArtifact. Ba trong số đó thay đổi cách bạn gắn thẻ tài liệu doanh nghiệp thông thường. Aside cuối cùng cho sidebar và pull quote một nơi ở không phải là một Sect bị dùng sai. FENote đánh dấu chú thích cuối trang và endnote đúng như bản chất của chúng, để trình đọc có thể đưa chúng ra thay vì chen vào thân bài. EmStrong thay thế phép đoán ngữ nghĩa đến từ việc gắn nhấn mạnh dưới dạng định dạng mức span

Overload chuỗi bổ sung chấp nhận dạng Hn mở rộng, bao gồm H7 trở đi. PDF 1.7 dừng ở H6, điều ép các tài liệu kỹ thuật sâu phải san phẳng đề cương hoặc tái sử dụng cấp. Nếu bạn sinh tài liệu chuẩn, luật văn bản hay danh mục bộ phận, chính điều này thôi cũng có thể là lý do để chuyển đầu ra sang PDF 2.0

Cần kiểm tra gì trước khi chuyển đầu ra sản xuất

PDF 2.0 là một thay đổi header với một đuôi dài. Các công cụ ingest kho lưu trữ cũ, một số RIP in và một số lượng đáng ngạc nhiên trình xem line-of-business chỉ chấp nhận đến PDF 1.7, và chúng thất bại trên header chứ không phải trên bất cứ điều gì bạn làm sai. Trước khi chuyển, hãy xác nhận các hệ thống tiêu thụ, và nhớ rằng chọn một profile PDF/A-4 nghĩa là chọn PDF 2.0 dù bạn có yêu cầu hay không

Một thứ tự an toàn là giữ PDF/A-3 cho các tài liệu đi ra ngoài tới độc giả không xác định, dùng PDF/A-4f cho kho lưu trữ nội bộ nơi bạn kiểm soát ingest, và áp dụng PDF/UA-2 chỉ nơi chính sách khả năng tiếp cận chỉ định nó. Nếu bạn đang xử lý phía lưu trữ trước, các hướng dẫn về xác thực PDF/A, PDF/X và PDF/UA và về hóa đơn hybrid ZUGFeRD và Factur-X trên PDF/A-3 trình bày các lựa chọn profile quan trọng hơn cả con số phiên bản, còn các ghi chú về báo cáo preflight tự động cho thấy cách biến phán quyết thành một phần của build thay vì một bước thủ công

HotPDF xuất xưởng toàn bộ bề mặt tác giả PDF 2.0 dưới dạng mã VCL bản địa cho Delphi và C++Builder, nên đầu ra PDF/A-4 và PDF/UA-2 không cần engine ngoài hay redistributable nào — trang thành phần HotPDF liệt kê các profile và phiên bản RAD Studio được hỗ trợ