PDF/A a PDF/UA odpovedajú na dve otázky, ktoré spolu nemajú nič spoločné, a práve to, že sa berú ako jediné zaškrtávacie políčko pre archiváciu a prístupnosť, vedie k tomu, že do archívu prídu pokazené súbory s nálepkou súladu. PDF/A sa pýta, či sa súbor o dvadsať rokov ešte vykreslí verne. PDF/UA sa pýta, či ho dnes dokáže prečítať asistenčná technológia. Dokument môže jedno bez problémov prejsť a v druhom neuspieť, takže úprimný verdikt dá len spustenie oboch, a to ešte pred zápisom súboru, nie až keď nadväzujúci systém uverí identifikátoru zhody zapečenému v jeho metadátach. Tento identifikátor je vyhlásením samotného producenta. Nič vo formáte nevyžaduje, aby bol pravdivý, a aplikácia, ktorá do XMP zapíše „PDF/A-1b“ bez validácie voči norme, vyprodukuje súbor, ktorý vyzerá vyhovujúco pre každého konzumenta čítajúceho iba nálepku. Knižnica losLab PDF Library (PDF Library for Delphi) túto medzeru pre Delphi a C++Builder zatvára tým, že oba validátory zabudováva priamo do knižnice, takže kontrola beží v procese a nepotrebuje žiadnu externú službu
Dve normy, ktoré nechávajú súbory prepadnúť z opačných dôvodov
Norma ISO 19005 (PDF/A) je kontraktom o reprodukcii. Vyhovujúci súbor sa musí o desaťročia vykresliť identicky na softvéri, ktorý nikdy nevidel systém, čo ho vyrobil, takže jej pravidlá útočia na externé závislosti: každé písmo vložené, farba ukotvená vo vloženom ICC profile OutputIntent alebo vyjadrená v priestore nezávislom od zariadenia, žiadne šifrovanie v PDF/A-1, žiadny JavaScript, metadáta XMP zhodné so slovníkom informácií o dokumente. Norma ISO 14289 (PDF/UA) je naproti tomu kontraktom o sémantike. Asistenčná technológia musí dokument prejsť a odniesť si z neho význam, ktorý sídli v úplne inej vrstve: kompletný strom štruktúry, alternatívny text pri obrázkoch, nastavený názov dokumentu na zobrazenie, úrovne nadpisov, ktoré nepreskakujú, vzťahy hlavičiek tabuliek, ktoré prežijú aj mimo obrazovky
Keďže obe normy dozerajú na odlišné vrstvy, poštípu vás práve tie súbory, ktoré sedia medzi nimi. Archívne dokonalý dokument môže byť pre čítačku obrazovky nemý. Nádherne otagovaný dokument môže odkazovať na desktopové písmo, ktoré o desať rokov nebude existovať. Publikovanie vo verejnom sektore je zvyčajným miestom, kde obe požiadavky dopadnú naraz, a tamojšia pipeline ich nemôže zliať do jedinej brány. Nálezy putujú k rôznym ľuďom. Nevložené písma sú chybou v kóde, ktorý PDF generuje, kým chýbajúci alternatívny text patrí tomu, kto vlastní obsahové šablóny, a report, ktorý oboje mieša, sa jednoducho preposiela dvakrát
Na tom, ktorú časť PDF/A si zvolíte za cieľ, záleží rovnako ako na tom, či ju trafíte. PDF/A-1 je zamrznuté na PDF 1.4 a odmieta priehľadnosť aj JPEG2000, po oboch pritom moderný reportovací výstup siaha bez rozmýšľania. PDF/A-2 (ISO 19005-2, postavené na ISO 32000-1) prijíma oboje a je rozumnou predvoľbou pre nový archív. PDF/A-3 ide ďalej a povoľuje vložené súbory ľubovoľného typu, na čom stoja regulované formáty elektronickej fakturácie. Tím, ktorý v roku 2026 stále štandardizuje na PDF/A-1b, obvykle nesie požiadavku, ktorú niekto napísal pred pätnástimi rokmi, a prerokovať cieľovú časť normy býva lacnejšie než odstraňovať priehľadnosť z každého grafu, ktorý systém vydá
Štruktúrované nálezy v čase príjmu
Vstupným bodom plochého API je CheckFileCompliance so selektorom testu 1 pre PDF/A a 2 pre PDF/UA. Vracia handle zoznamu reťazcov, ktorého položkami sú jednotlivé nálezy, jeden na riadok, čo je presne ten tvar, ktorý chce automatizovaná brána prejsť:
function GateArchiveUpload(Pdf: TPDFlib; const FileName: string): Boolean;
var
ListId, I: Integer;
begin
ListId := Pdf.CheckFileCompliance(FileName, '', 1, 0); // 1 = PDF/A
if ListId = 0 then
begin
// 0 znamená "žiadne nálezy" ALEBO "súbor sa nedá čítať" -- rozlíšte pred prepustením
Result := Pdf.LastErrorCode = 0;
Exit;
end;
for I := 0 to Pdf.GetStringListCount(ListId) - 1 do
LogFinding(FileName, Pdf.GetStringListItem(ListId, I));
Pdf.ReleaseStringList(ListId);
Result := False;
end;
O tom, či to pobeží bez dozoru, rozhodujú dva detaily. Prvým je návratová hodnota, ktorá znamená dve opačné veci. CheckFileCompliance vracia 0, keď je súbor plne vyhovujúci, ale aj vtedy, keď sa súbor vôbec nepodarilo otvoriť, pretože prázdny zoznam výsledkov sa vnútri v oboch prípadoch zredukuje na 0. Brána, ktorá číta 0 ako prechod, prepustí poškodené nahrávky rovno do archívu, takže než nule uveríte, rozlíšte prípady cez LastErrorCode, tak ako to robí brána vyššie. Druhý detail sa týka toho, kde sa súbor nachádza vo svojom životnom cykle. Kontrola beží nad streamovacou čítačkou knižnice namiesto nad plným modelom dokumentu, súbor otvára priamo so zdieľaním na čítanie a nikdy nevolá LoadFromFile, vďaka čomu prežuje aj viacgigabajtový vstup bez stavania objektového stromu. To isté streamovacie otvorenie zlyhá, kým iný proces súbor stále drží na zápis, a prebiehajúce nahrávanie je presne takým stavom. Bránu umiestnite až za dokončenie prenosu
Streamovací návrh sa vypláca aj pod záťažou. Každá kontrola otvorí svoj vstup len na čítanie a zdieľa ho na čítanie, takže audit celého korpusu sa škáluje naprieč pracovnými vláknami alebo procesmi s jednou inštanciou TPDFlib na pracovníka a bez vzájomnej kolízie. Zdrojom, ktorý si vyžaduje disciplínu, je samotný handle. Každý nenulový výsledok z CheckFileCompliance zostáva alokovaný, kým nezavoláte ReleaseStringList, a dlhobežiaca brána, ktorá na uvoľňovanie zabudne, nespadne, len pomaly krváca pamäťou, až kým niekto nezačne pátrať prečo
Reporty pre ľudí, diffy pre brány buildu
Zoznam nálezov má správny tvar pre bránu a nesprávny tvar pre e-mail tímu, ktorý spravuje šablóny. CreatePreflightReport vykreslí tú istú analýzu ako čitateľnú prózu, CreatePreflightReportEx pridáva selektor formátu reportu a SavePreflightReport ho zapíše na disk, takže report môže cestovať vnútri dodaného balíka dokumentov. Nemálo archívnych zmlúv robí z tohto reportu samostatný predmet dodania, nielen interný artefakt
Členom tejto rodiny, ktorý si svoje miesto zaslúži nenápadne, je ComparePreflightReports. Súlad je regresnou plochou ako ktorákoľvek iná časť správania. Úprava šablóny, novo licencované firemné písmo alebo aktualizácia knižnice môžu každá zaviesť nález, ktorý pri minulom vydaní neexistoval, a ani jedna sa neohlási sama. Držte referenčné reporty pre sadu reprezentatívnych dokumentov pod správou verzií, po každej zmene ich znovu vygenerujte a rozdiel spočítajte cez ComparePreflightReports. Prázdny diff je artefaktom vydania, ktorý sa oplatí uchovať. Prekvapivý nález zhodí build, a to je oveľa lacnejšie miesto na jeho objavenie než audit
Generovanie výstupu, ktorý prejde na prvý raz
Preflight sa vypláca pri súboroch prichádzajúcich odinakiaľ. Pri dokumentoch, ktoré produkuje váš vlastný kód, je hľadanie porušení po generovaní a ich dodatočné záplatovanie tou pomalšou cestou. PDF Library for Delphi nesie pre každú normu režim na strane generovania a oba môžete zapnúť pre ten istý dokument:
var
Pdf: TPDFlib;
Diag: WideString;
begin
Pdf := TPDFlib.Create;
try
Pdf.NewDocument;
Pdf.SetPDFAMode(1);
Pdf.LoadOutputIntentProfile('sRGB-IEC61966-2.1.icc', 'RGB');
Pdf.SetPDFUAMode('en-US');
Pdf.SetInformation(1, 'Quarterly Statement'); // /Title: povinné pre PDF/UA
// ... sem sa kreslí otagovaný obsah ...
Diag := Pdf.GetPDFUADiagnostics;
if Diag <> '' then
Writeln('fix before shipping: ', Diag);
Pdf.SaveToFile('statement.pdf');
// preflight, na ktorom záleží, beží nad uloženým súborom:
Writeln(Pdf.CreatePreflightReport('statement.pdf', '', 1, 0));
finally
Pdf.Free;
end;
end;
Pasca sa skrýva v čase ukladania. Viacero opráv pre zhodu s normou sa deje počas serializácie dokumentu, nie vtedy, keď režim zapnete: vynútenie tlačového príznaku na anotáciách, zápis predvoleného AFRelationship pre vložené súbory v PDF/A-3, normalizácia poradia tabulátora a popisov formulárových polí pre PDF/UA. Dokument sediaci v pamäti nie je bajtovo identický s tým, ktorý pristane na disku, takže jediný preflightový verdikt, ktorý má nejakú váhu, je ten spočítaný z uloženého súboru. Validujte samotný statement.pdf. Nevyvodzujte súlad z objektu, ktorý je stále v pamäti, pretože bajty, ktoré by ste posudzovali, nie sú tie, ktoré ste odoslali
Fakturačné scenáre, ktoré popri vizuálnom dokumente nesú strojovo čitateľné XML, sa riadia vzorom ZUGFeRD a Factur-X postaveným na PDF/A-3. Tie by mali vzťah prílohy nastaviť explicitne cez SetPDFA3DefaultAFRelationship, keďže ISO 19005-3 vyžaduje, aby každý vložený súbor deklaroval svoju rolu voči dokumentu. Nechajte to nenastavené a vložené XML je len blob bez uvedeného účelu, čoho si validátor všimne
Nezávislí rozhodcovia: veraPDF a Acrobat
Producent by nemal byť jediným sudcom vlastného výstupu. Kontrolóry v PDF Library for Delphi vám dávajú rýchle štruktúrované verdikty priamo v procese, čo je presne to, čo chcete na horúcej ceste, ale brána vydania pre archívnu dávku by mala výstup aj tak prehnať validátorom, ktorý nepísal nikto z vášho tímu. veraPDF je komunitne udržiavanou referenčnou implementáciou pre PDF/A a nástrojom, ktorý väčšina archívov menuje vo svojich akceptačných kritériách, takže práve jemu sa treba vyrovnať. Preflightové profily Acrobatu sú užitočným rozhodcom, keď sa veraPDF a kontrola v procese nezhodnú. Ku každému uloženému reportu si zapíšte názov validátora a jeho verziu. Tvrdenie, že súbor prešiel cez veraPDF, hovorí veľmi málo bez čísla buildu, ktorý ho prepustil, pretože nástroj medzi vydaniami svoje pravidlá uťahuje
Validátory sa na okrajoch noriem naozaj rozchádzajú a keď sa tak stane, odpoveďou nie je vybrať si nástroj, ktorý sa vám páči. Zmenšite súbor na minimálnu vzorku, ktorá nezhodu stále vyvolá, a prečítajte si ju oproti textu normy. Hodina takejto práce zvyčajne odhalí jednu z dvoch vecí: skutočnú chybu nástroja, ktorú sa oplatí nahlásiť jeho autorom, alebo ustanovenie, ktoré si váš tím dlhodobo vykladá zle a mal by si ho zapísať do poznámok k súladu, aby ho ďalší človek neriešil odznova
Šifrovaný vstup má skratku. Oba kontrolóry prijímajú argument s heslom, ale súbor PDF/A-1 so slovníkom šifrovania už vyhovujúci nie je, pretože ISO 19005-1 šifrovanie priamo zakazuje, takže šifrované podanie sa dá odmietnuť ešte pred akoukoľvek hlbšou analýzou. Zistiť, čo slovník šifrovania vlastne povoľuje, je samostatná úloha, ktorú pokrýva článok o šifrovaní PDF a audite oprávnení
Nálezy PDF/UA sa takmer vždy dajú vystopovať k tomu, ako bol strom štruktúry pôvodne vytvorený, a tagovacie techniky za tým sídlia v článku o budovaní stromov štruktúry v otagovanom PDF v Delphi. Archívy, ktoré žiadajú aj digitálne podpisy, by mali túto bránu spárovať s pracovným postupom z článku o podpisovaní a validácii PAdES. Kompletná referencia preflightového API sídli na stránke produktu losLab PDF Library for Delphi