ConvertToPDFA biến một tài liệu thông thường thành tài liệu lưu trữ chỉ trong một lệnh gọi: nó gỡ bỏ những gì part đã chọn cấm, thêm những gì part yêu cầu, khai báo part mà tài liệu cam kết, rồi kiểm tra kết quả. Cam kết chỉ được báo cáo là đạt khi phép kiểm tra vượt qua, và GetPDFAConversionReport liệt kê những gì đã làm cùng những gì vẫn còn cản trở
Tính chất cuối cùng ấy chính là quyết định thiết kế đáng bàn kỹ. Một bộ chuyển đổi đóng dấu cam kết mà không kiểm tra thì tệ hơn không có bộ chuyển đổi nào cả, vì một file nói rằng nó là tài liệu lưu trữ mà thực ra không phải sẽ lọt thẳng qua chính những hệ thống đáng lẽ phải bắt được nó. Sự cố lộ ra nhiều năm sau, trong một cuộc kiểm toán, trên một tài liệu mà không ai có thể tạo lại
Vì sao một PDF có vẻ hợp lệ lại trượt phép kiểm tra PDF/A?
Phổ biến nhất là vì hai nơi mà một PDF nói ai đã viết nó lại không đồng ý với nhau. Một trình xác thực đọc cả document information dictionary lẫn gói XMP và từ chối một file mà chúng khác nhau — và phần lớn các file hỏng ở điểm này đơn giản là chưa từng được ghi phần XMP
RepairDocumentMetadata đưa chúng về đồng nhất và trả về số mục đã sửa. Nơi chỉ một nửa mang giá trị, nửa kia được điền từ nửa đó, nên không có gì đã ghi lại bị vứt bỏ. Không ai phải quyết định bản sao nào đáng tin cậy, vì trên thực tế một bản sao là rỗng
Có một phép sửa thứ hai trong cùng lệnh gọi, bắt một trường hợp tinh tế hơn. Một tài liệu được đặt sang chế độ PDF/A sẽ được khôi phục nhận diện chuẩn nếu nó bị mất, điều xảy ra mỗi khi bên gọi tự cung cấp một gói XMP riêng. Thiếu nhận diện đó, một trình xác thực đọc file như một PDF thông thường và báo cáo mọi quy tắc của part đã cam kết là chưa đáp ứng — một thất bại trông rất hoành tráng mà nguyên nhân chỉ là một chi tiết nhỏ
var
Lib: TPDFlib;
Repaired: Integer;
begin
Lib := TPDFlib.Create;
try
Lib.LoadFromFile('incoming.pdf', '');
Repaired := Lib.RepairDocumentMetadata;
Log(Format('%d metadata entries brought into agreement', [Repaired]));
Lib.SaveToFile('incoming-fixed.pdf');
finally
Lib.Free;
end;
end;
Chọn part trước khi chuyển đổi
SetPDFAMode và ConvertToPDFA dùng chung cách đánh số chế độ, và ba trong số các giá trị là mới. Chế độ 9 là PDF/A-4, part xây trên PDF 2.0. Chế độ 10 là PDF/A-4e, thêm phép cho 3D và rich media, còn chế độ 11 là PDF/A-4f, cho phép một tệp nhúng với định dạng bất kỳ
Part 4 tự nhận diện khác với các part trước nó: theo số part và năm xuất bản, không có chữ cái conformance cho PDF/A-4 thuần và chữ E hoặc F cho hai phần mở rộng. Phép kiểm tra nhận ra part 4, đánh giá file theo PDF 2.0 thay vì 1.7, và báo cáo một file part 4 không khai báo năm hiệu đính
Mọi tệp nhúng trong một tài liệu part 4 đều khai báo quan hệ của nó với tài liệu, đúng như cả part 3 và part 4 đều yêu cầu. Đây là quy tắc từng bắt các tệp đính kèm thông thường: quan hệ chỉ được ghi cho các đính kèm sau cái đầu tiên và không bao giờ cho cái cuối cùng, nên một tài liệu chỉ có một tệp đính kèm — trường hợp phổ biến — lại không mang quan hệ nào cả và thất bại xác thực ở đúng điểm đó
var
Verdict: Integer;
begin
Lib.LoadFromFile('report.pdf', '');
Verdict := Lib.ConvertToPDFA(9); // 9 = PDF/A-4, 10 = 4e, 11 = 4f
Memo1.Lines.Text := Lib.GetPDFAConversionReport;
if Verdict = 1 then
Lib.SaveToFile('report-pdfa4.pdf')
else
Log('conversion incomplete - see the report for what stands in the way');
end;
Báo cáo chuyển đổi để làm gì
Để quyết định bước tiếp theo. Một chuyển đổi thành công không cần báo cáo; một chuyển đổi chưa xong là toàn bộ lý do báo cáo tồn tại. Một số trở ngại có thể gỡ bởi bộ chuyển đổi, một số không — mã hóa, nội dung bị cấm mang ý nghĩa, một font program đơn thuần không có ở bất cứ đâu trên máy. Báo cáo phân biệt những gì đã làm với những gì còn lại, biến "chuyển đổi thất bại" thành một mục công việc
Hãy coi phán quyết như cổng vào trong một pipeline hàng loạt. Chuyển đổi, đọc phán quyết, rồi định tuyến tệp: lưu trữ những tệp đạt, đưa những tệp còn lại vào hàng đợi cho con người kèm theo báo cáo. Điều bạn không nên làm là lưu đầu ra của một chuyển đổi thất bại vào kho lưu trữ chỉ vì nó trông đẹp hơn đầu vào — nó giờ mang một cam kết mà phép kiểm tra đã từ chối xác nhận
Đọc dấu mà một tệp đã mang theo
Trước khi chuyển đổi bất cứ thứ gì, hãy biết tài liệu nói gì về chính nó. Một phép kiểm tra PDF/A không đọc được dấu chuẩn hiện có sẽ đánh giá mọi file theo part 1 bất kể nó khai báo gì, nghĩa là một tài liệu PDF/A-2 hoặc PDF/A-3 hoàn toàn hợp lệ bị báo cáo là không mang dấu và có phiên bản quá cao — điều ngược lại với sự thật
Dấu được đọc bất kể nơi sản xuất đã ghi nó như một phần tử XMP hay như một thuộc tính. Cả hai dạng đều là XMP thông thường, và chỉ chấp nhận một dạng sẽ để các file từ các nhà sản xuất khác trông như chưa được đánh dấu. Nếu bạn từng tự hỏi vì sao một tài liệu xác thực được ở nơi khác lại thất bại trong chính pipeline của bạn, đây là nơi đáng xem đầu tiên
Làm sạch trước khi lưu trữ, và một bug đáng biết
Chuyển đổi lưu trữ và làm sạch thường chạy cùng nhau, vì nội dung mà một chính sách bảo mật muốn gỡ bỏ trùng lặp nặng với nội dung mà PDF/A cấm. SanitizeDocument gỡ bỏ JavaScript, và việc gỡ script cuối cùng cũng gỡ luôn cây tên rỗng mà nó để lại — một cây mà nếu không sẽ vẫn báo cho trình đọc rằng tài liệu có mang script
Nửa sau đó là bài học xương máu: một lỗi off-by-one trong danh sách gói khiến làm sạch báo là đã gỡ script trong khi không gỡ gì cả, nên một tài liệu đã được làm sạch vẫn chạy script khi mở. Đó là một luận cứ tốt cho nguyên tắc chung mà toàn bộ bài viết này dựa vào — xác thực kết quả thay vì tin vào thao tác, trong pipeline của bạn cũng như trong thư viện
Về công việc lưu trữ xung quanh, hãy xem các bài viết về PDF/A và PDF/UA preflight, redaction thật sự và gỡ bỏ nội dung, cùng lược đồ mở rộng XMP PDF/A-3 cho Factur-X, bài này trình bày phía siêu dữ liệu khi tài liệu lưu trữ còn mang theo dữ liệu hóa đơn có cấu trúc
PDFlibPas là thư viện PDF Pascal bản địa cho Delphi, C++Builder và Lazarus, nên chuyển đổi, sửa và xác thực đều diễn ra trong tiến trình của bạn mà không có công cụ ngoài trong chuỗi — xem trang sản phẩm PDFlibPas để biết các part PDF/A và nền tảng được hỗ trợ