Failas jūsų kompiuteryje atsidaro be jokių problemų. „Acrobat“ jį rodo, spaudinio peržiūra atrodo tinkama, visi puslapiai yra savo vietose. Tačiau vėliau jis išsiunčiamas į spaustuvę arba archyvavimo sistemą, kuri apdoroja jūsų mėnesinę partiją, ir grąžinamas kaip atmestas: RGB vaizdai CMYK užduotyje, nėra /Trapped rakto, išvesties paskirtis (angl. output intent) neatitinka spaudos mašinos parametrų. Vizualiai su dokumentu viskas atrodė gerai. Tačiau jis neatitiko profilio reikalavimų, o profilis buvo tikrinamas kitoje sistemoje, prie kurios neturėjote prieigos. „Preflight“ (pirminis patikrinimas) yra šio patikrinimo pavadinimas spaudos pramonėje, o tikrasis klausimas, kurioje vietoje ši patikra turėtų vykti, kai PDF failai yra generuojami tiesiai iš jūsų „Delphi“ kodo, o ne iš dizainerio darbalaukio.
„HotPDF“ nesuteikia iškviečiamos „preflight“ funkcijos. Komponento grafinėje (GUI) demonstracinėje programoje yra „preflight“ ataskaitos langas, tačiau po juo nėra jokios API, kurią galėtų iškviesti paslauga ar kūrimo scenarijus (angl. build script). Bandymas teigti kitaip tik priverstų jus ieškoti metodo, kurio tiesiog nėra. Tai gali atrodyti kaip trūkumas, kol nesuprantate, kad jūsų pačių sugeneruotiems failams tikrinimo programos (validatoriaus) iškvietimas jūsų pačių išvestyje bet kokiu atveju yra neteisingas požiūris. Jūs jau dabar kontroliuojate kiekvieną savybę, kurią tikrintų validatorius. Naudingiausia yra sukonfigūruoti generavimo procesą taip, kad jis tiesiog negalėtų sukurti netinkamo failo, o tada tai įrodyti naudojant įrankį, kurio patys neparašėte.
Kodėl savo pačių sugeneruotus failus tikrinate kitaip
Tradicinė „preflight“ patikra yra skirta svetimiems failams. Juos sukūrė kažkoks dizaineris, kita programa ar nežinoma redagavimo grandinė, todėl tikrinate juos neturėdami supratimo, kas yra viduje. Dokumentas, kurį sukūrė jūsų kodas, nėra svetimas. Šriftų įterpimą, spalvų erdvę, išvesties paskirtį, metaduomenų bloką: jūsų programa visa tai nusprendė likus kelioms milisekundėms iki failo įrašymo į diską. Tikrinti failą vėliau, kad sužinotumėte savo pačių ką tik atliktus pasirinkimus, yra perteklinis darbas. Daug efektyviau yra apriboti šiuos pasirinkimus taip, kad reikalavimų neatitinkantis failas net negalėtų būti sukurtas.
Taip pat yra patikimumo priežastis, kodėl vertinimą reikėtų palikti išoriniam įrankiui. Biblioteka, kuri pati patvirtina savo išvestį, pati vertina savo egzaminą. Kai kliento archyvavimo sistema arba spaustuvės RIP (rastrinių vaizdų procesorius) atmeta jūsų failą, teiginys „mūsų komponentas sako, kad viskas gerai“ neturi jokios galios. Tačiau „veraPDF“ ar „Acrobat“ išvados turi svorį, nes kita šalis naudoja tuos pačius įrankius.
Padarykite atitiktį nustatymu, o ne kontroliniu sąrašu
Prevencijos sluoksnis yra tiesiog konfigūracija. Nustatykite PDFACompliance arba PDFXCompliance prieš kviesdami BeginDoc ir „HotPDF“ pritaikys atitinkamas taisykles visam generavimo etapui: įterps šriftus, stebės DeviceRGB ir DeviceCMYK naudojimą pagal jūsų deklaruotą išvesties paskirtį bei atmes funkcijas, kurias draudžia profilis. Neatitikimai išryškėja ties EndDoc, kur atitikties kontrolė sustabdo procesą, užuot tyliai išsiuntusi failą, kuris vėliau bus atmestas. Įrašius failą, tos pačios savybės leidžia nuskaityti, kas buvo pritaikyta, o tai yra pati svarbiausia informacija jūsų proceso žurnale:
// After EndDoc: record the enforced profiles with the run metadata
if Pdf.PDFACompliance <> '' then
Log('Generated as PDF/A level ' + Pdf.PDFACompliance);
if Pdf.PDFXCompliance <> '' then
Log('Generated as PDF/X profile ' + Pdf.PDFXCompliance);
Įrašykite šiuos požymius į tą pačią žurnalo eilutę kartu su įvesties duomenų maišos (hash) reikšme ir „HotPDF“ versija. Tą dieną, kai validatorius ir jūsų generavimo programa nesutars dėl failo būsenos, ši eilutė nurodys, kuris šablonas jį sukūrė ir kuri bibliotekos versija buvo įkelta, o ginčas, kuris kitu atveju atimtų visą popietę, bus išspręstas viena „grep“ komanda. Išvesties paskirtys, ICC profiliai ir žymėjimas (angl. tagging), kuriais remiasi šie požymiai, yra išsamiai aprašyti PDF/A, PDF/X ir PDF/UA dokumentų kūrimo su „HotPDF“ vadove.
Greitas pirminis filtras failams, kurių negeneravote patys
Ne kiekvienas procesas yra tik generavimas. Klientai įkelia PDF failus, skeneriai deda juos į aplanką, partneriai prideda prie el. laiškų. Siųsti kiekvieną iš šių failų į pilną struktūrinį validatorių yra laiko švaistymas, ypač jei failai net negali atsidaryti. „HotPDF“ Direct File API nuskaito pakankamai failo struktūros, kad atsakytų į klausimą „ar tai apskritai tinkamas PDF failas“, neįkeliant viso objektų medžio, todėl tai yra puiki vieta greitam klaidų nustatymui:
function TriagePdf(Pdf: THotPDF; const FileName: string): Boolean;
var
Handle, Pages: Integer;
begin
Result := False;
Handle := Pdf.DAOpenFileReadOnly(FileName, '');
if Handle <= 0 then
Exit; // structurally unreadable: quarantine, do not validate
try
Pages := Pdf.DAGetPageCount(Handle);
Result := Pages > 0;
finally
Pdf.DACloseFile(Handle);
end;
end;
Šios API naudojimo būdą lemia du faktai. Supaprastintas atminties nuskaitymas veikia tik su nešifruota įvestimi; pateikus DAOpenFileReadOnly slaptažodį, sistema tyliai grįžta prie pilno apdorojimo, zodžiu, žinomai šifruotas failas prieš pirminį filtravimą turėtų būti apdorotas su DecryptFile į paprastą darbinę kopiją. Be to, DAGetPageCount neturi jokios prasmės, jei deskriptorius (angl. handle) nebuvo sėkmingai atidarytas, todėl deskriptoriaus patikra išlieka griežta ir neigiamas arba nulinis rezultatas reiškia atmetimą, o ne pakartotinį bandymą. Daugiau tokių pavyzdžių rasite Direct File API straipsnyje, skirtame didelių PDF failų procesams.
„veraPDF“ integracija į kūrimo procesą
Visiems failams, kurių deklaruojate kaip atitinkančius PDF/A arba PDF/UA standartus, rekomenduojama integruoti „veraPDF“ validatorių. Jis veikia be naudotojo sąsajos (headless), priima failų partijas, pateikia rezultatus XML arba JSON formatu ir nurodo kiekvieną klaidą pagal atitinkamą ISO punktą. Pavyzdžiui, taisyklės pažeidimas pagal ISO 19005-1 6.2.2 punktą iškart nurodo generavimo programos nustatymą, todėl jums nereikia spėlioti. Jo valdymas iš „Delphi“ yra paprastas procesų kontrolės uždavinys:
function RunVeraPdf(const PdfFile, ReportFile: string): Cardinal;
var
Cmd: string;
SI: TStartupInfo;
PI: TProcessInformation;
begin
Cmd := Format('cmd /c verapdf.bat --format xml "%s" > "%s"',
[PdfFile, ReportFile]);
FillChar(SI, SizeOf(SI), 0);
SI.cb := SizeOf(SI);
if not CreateProcess(nil, PChar(Cmd), nil, nil, False,
CREATE_NO_WINDOW, nil, nil, SI, PI) then
RaiseLastOSError;
try
WaitForSingleObject(PI.hProcess, 120000); // bound the wait per file
GetExitCodeProcess(PI.hProcess, Result);
finally
CloseHandle(PI.hThread);
CloseHandle(PI.hProcess);
end;
end;
Šis laiko limitas (timeout) yra itin naudingas. Sugadintas failas gali užstrigdinti bet kurį analizatorių (parser), o neribotas laukimas eilės apdorojimo procese sustabdys visų kitų failų apdorojimą. Apribokite laukimo laiką, priskirkite atskirą klaidos kodą laiko viršijimui ir atidėkite failą rankiniam patikrinimui. Skaitydami rezultatus, XML faile ieškokite taisyklių identifikatorių (Rule IDs), o ne teksto, skirto skaityti žmonėms. Taisyklių ID nesikeičia atnaujinant validatorių, o pranešimų formuluotės gali pasikeisti. Stabilus kodas yra tai, pagal ką palaikymo inžinierius gali ieškoti informacijos senuose užklausų žurnaluose.
Kaip paleidžiate partijos apdorojimą, yra taip pat svarbu, kaip ir tai, ar kiekvienas failas praeina patikrą. Naudokite po vieną procesą kiekvienam failui, o ne vieną visai partijai, kad sugadintas failas kainuotų tik to konkretaus failo laukimo limitą ir nieko daugiau. Ribokite lygiagrečių validatoriaus procesų skaičių iki procesoriaus branduolių skaičiaus, nes XML ataskaitos kūrimas reikalauja daug procesoriaus resursų ir per didelis procesų skaičius tik sulėtins darbą. Taip pat nustatykite maksimalų failo dydžio limitą priėmimo metu, nes dviejų gigabaitų skenuota knyga užims visą eilę, kad ir koks kantrus būtų analizatorius. Griežtąja prasme tai nėra „preflight“ patikra, tačiau tai lemia skirtumą tarp sistemos, kuri sėkmingai atlaiko mėnesio pabaigos apkrovas, ir tos, kuri bus išjungta jau pirmą naktį, kai 2 val. nakties sustabdys visą procesą.
PDF/X atveju ši sistema turi trūkumų. „veraPDF“ jo netikrina, zodžiu, praktinis sprendimas išlieka „Acrobat Preflight“ su spaustuvės nurodytu ISO 15930 profiliu. „Acrobat“ reikalauja žmogaus įsikišimo, o tai reiškia atrankinį tikrinimą, o ne pilną aprėptį: patikrinamas pirmasis failas iš naujo šablono bei atsitiktinė nedidelė dalis failų iš kiekvienos partijos, kol automatinis filtras apdoroja visa kita, ką galima patikrinti be žmogaus pagalbos. Atrankinis patikrinimas, kuris yra realiai atliekamas, yra geriau nei visiškas automatizavimas, kuris taip ir lieka nebaigtas kurti.
Ataskaita, kurios jums prireiks ir po metų
„Preflight“ patikros filtras atsiperka du kartus. Pirmą kartą – kai sustabdo netinkamą failą prie durų, ir antrą kartą – gerokai vėliau, kai kas nors paklaus, kodėl tam tikras failas buvo praleistas. Šis antrasis atvejis turėtų nulemti ataskaitos formatą, nes trumpa, neinformatyvi ataskaita nepadės išspręsti problemos. Kiekvienam patikrintam failui išsaugokite įvesties maišos kodą, generavimo programos atitikties požymius ir bibliotekos versiją iš aukščiau nurodytos žurnalo eilutės, validatoriaus pavadinimą bei versiją, profilį, pagal kurį buvo atlikta patikra, rezultatą (pavyko/nepavyko) ir klaidų taisyklių ID kartu su puslapių numeriais. Saugokite šią ataskaitą šalia aprašomo failo. Jei padėsite ją į atskirą sistemą, tikėtina, kad ta sistema bus išjungta dar prieš sunaikinant patį archyvą.
Išimtys taip pat privalo būti fiksuojamos. Kai klientas primygtinai reikalauja išsiųsti failą, kurio filtras nepraleidžia, sprendimas nėra sušvelninti taisykles visiems. Užfiksuokite, kas patvirtino šį failą, kokiu pagrindu ir iki kurios datos, o tada pridėkite šį leidimą (waiver) prie ataskaitos. Leidimas su nurodyta pavarde ir galiojimo terminu yra sprendimas, už kurį kažkas atsako. O „laikinai“ užkomentuotas patikrinimas yra tik laiko klausimas, kada įvyks naujas incidentas.
Dar vienas naudingas įprotis: kai failo patikra nepavyksta, nukopijuokite jį į tam skirtą regresinių testų aplanką prieš kam nors jį keičiant. Beveik kiekviena „preflight“ problema, kurią verta derinti, kyla dėl vienos konkrečios įvesties. Komandos, kurios išsaugo tokius pavyzdžius, ištaiso pasikartojančias klaidas per valandą, užuot laukusios, kol jos vėl pasirodys gamybinėje aplinkoje. Čia parodytos atitikties savybės ir Direct File API yra „Delphi“ bei „C++Builder“ skirtos HotPDF Component dalis, kurios dokumentacijoje išsamiai aprašytas kiekvienas metodas.