Техническа статия

Преобразуване на PDF в PDF/A и поправяне на метаданните му

ConvertToPDFA превръща обикновен документ в архивен с едно извикване: премахва това, което избраната часть забранява, добавя това, което тя изисква, заявява частта, която документът претендира, и след това проверява резултата. Претенцията се отчита като изпълнена само когато проверката мине, а GetPDFAConversionReport изброява какво е било направено и какво все още стои на пътя

Точно последното свойство е проектното решение, върху което си струва да се спрем. Конвертор, който щампа претенция без да проверява, е по-лош и от никакъв конвертор, защото файл, който казва, че е архивен, без да е, преминава направо през системите, които иначе биха го хванали. Провалът се появява години по-късно, в одит, върху документ, който никой не може да регенерира

Защо валидно изглеждащ PDF не минава проверка за PDF/A?

Най-често защото двете места, на които PDF казва кой го е написал, не са съгласувани. Валидаторът чете и информационния речник на документа, и XMP пакета, и отхвърля файл, в който те се различават — а повечето файлове, които се провалят на този пункт, просто никога не са имали написана изобщо XMP половината

RepairDocumentMetadata ги привежда в съгласие и връща колко записа е поправил. Където само едната половина носи стойност, другата се запълва от нея, така че нищо вече записано не бива изхвърлено. Никой не трябва да решава кое копие е авторитетно, защото на практика едно копие е празно

Има втора поправка в същото извикване, която хваща по-тънък случай. Документ, установлен в режим PDF/A, получава възстановена идентификацията си на стандарта, ако е била загубена — което се случва всеки път, когато извикващият достави собствен XMP пакет. Без тази идентификация валидаторът чете файла като обикновен PDF и отчита всяко правило на заявяната част като неизпълнено — зрелищно изглеждащ провал с една малка причина

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;

Избор на частта преди преобразуване

SetPDFAMode и ConvertToPDFA споделят едно и също номериране на режими, и три от стойностите са скорошни. Режим 9 е PDF/A-4, частта, построена върху PDF 2.0. Режим 10 е PDF/A-4e, който допълнително разрешава 3D и богати медийни обекти, а режим 11 е PDF/A-4f, който разрешава вграден файл от всякакъв формат

Част 4 се идентифицира различно от частите преди нея: по номер на част и годината на публикуване, без буква на съответствие за обикновен PDF/A-4 и с буквата E или F за двете разширения. Проверката разпознава част 4, съди нейните файлове спрямо PDF 2.0 вместо 1.7, и отчита файл на част 4, който не заявява своята година на ревизия

Всеки вграден файл в документ на част 4 заявява как се отнася към документа, както изискват и части 3, и 4. Това е правилото, което по-рано хващаше обикновени прикачени файлове: отношението се записваше само за прикачени файлове след първия и никога за последния, така че документ с единствен прикачен файл — честият случай — не носеше никакъв и не минаваше валидация точно на този пункт

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;

За какво служи отчетът за преобразуване

За да решите какво да правите по-нататък. Успешно преобразуване не се нуждае от отчет; неуспешно преобразуване е цялата причина отчетът да съществува. Някои препятствия са премахваеми от конвертор, а други не — криптиране, забранено съдържание, което носи смисъл, шрифтов програма, която просто не присъства никъде на машината. Отчетът разграничава това, което е било направено, от това, което остава, което превръща «преобразуването се провали» в работна задача

Отнасяйте се към присъдата като към врата в пакетен пайплайн. Преобразувайте, четете присъдата и насочвайте файла: архивирайте тези, които са минали, а останалите на опашка за човек с прикачен отчет. Каквото не трябва да правите, е да запазвате изхода от неуспешно преобразуване в архива, защото изглежда по-добре от входа — той вече носи претенция, която проверката отказа да потвърди

Четене на марката, която файлът вече носи

Преди да преобразувате каквото и да е, трябва да знаете какво документът казва за себе си. Проверка за PDF/A, която не може да прочете съществуващата марка на стандарта, съди всеки файл спрямо част 1, каквото и да декларира, което означава, че напълно валиден PDF/A-2 или PDF/A-3 документ бива отчитан като носещ никаква марка и като с твърде висока версия — противоположното на истината

Марката се чете независимо дали продуцентът я е записал като XMP елемент или като атрибут. И двете форми са обикновен XMP, и приемането само на едната оставя файлове от други продуценти да изглеждат немаркирани. Ако някога сте се чудили защо документ, който минава валидация другаде, се проваля във вашия собствен пайплайн, това е доброто място да погледнете първо

Обеззаразяване преди архивиране и бъгът, който си струва да се знае

Архивното преобразуване и обеззаразяването често работят заедно, защото съдържанието, което иска да премахне една политика за сигурност, силно се застъпва със съдържанието, което PDF/A забранява. SanitizeDocument премахва JavaScript, а премахването на последния скрипт премахва и празното дърво с имена, което той оставя след себе си — дърво, което иначе все още би казало на четеца, че документът е носил скриптове

Втората половина беше научена по трудния начин: грешка «с едно повече» в списъка с пакети означаваше, че обеззаразяването отчиташе премахнати скриптове, без да премахне нито един, така че документ, който е бил обеззаразен, все още изпълняваше скриптовете си при отваряне. Това е добър аргумент за общия принцип, върху който цялата тази статия почива — верифицирайте резултата вместо да се доверявате на операцията, във вашия собствен пайплайн толкова, колкото в библиотеката

За околната архивна работа вижте ръководствата за PDF/A и PDF/UA предполетна проверка, истинско редактиране и премахване на съдържание и XMP схеми за разширение на PDF/A-3 за Factur-X, която разглежда страната на метаданните, когато архивираният документ носи и структурирани данни за фактура

PDFlibPas е нативна Pascal PDF библиотека за Delphi, C++Builder и Lazarus, така че преобразуване, поправка и валидация се случват вътре във вашия собствен процес без външен инструмент в веригата — вижте страницата на продукта PDFlibPas за поддържаните PDF/A части и платформи