Tekninen artikkeli

Eräajettavat (Batch) PDF-ennakkotarkastusraportit (Preflight Reports) Delphissä PDFium Component -komponentin (PDFium Component) CLI:llä

Eräajopohjainen esitarkastustyökalu on konsoliohjelma ilman ikkunaa, joka osoitetaan PDF-tiedostoja sisältävään kansioon, validoi jokaisen nimeämiäsi vaatimustenmukaisuusstandardeja vasten ja jättää jälkeensä koneluettavan todisteen siitä, mitä se löysi Kukaan ei istu katsomassa sitä Se ajetaan kello kahdelta yöllä cronin tai Windowsin tehtävienajastimen alla tai porttina CI-putkessa, ja seuraava sen tulosteesta välittävä on joko ajastin, joka lukee poistumiskoodin, tai auditoija, joka avaa raportin viikkoja myöhemmin Se muuttaa sitä, mitä "oikein" tarkoittaa PDFium Componentin, Delphille, C++Builderille ja Lazarukselle tarkoitetun lähdekoodillisen PDF-kirjaston, esitarkastusmoottori tekee itse validointikutsuista lähes triviaaleja Työ, joka ratkaisee ansaitseeko työkalu paikkansa, sijaitsee noiden kutsujen ympärillä: mikä profiili tarkistettiin, mitä poistumiskoodi kertoi ajastimelle, ja onko raportti, joka olisi napannut virheen, vielä olemassa, kun joku menee etsimään sitä

Sopimus: mitä ajastin oikeasti näkee

CI-ajaja tai Windowsin tehtävienajastin näkee työkalustasi tasan kaksi asiaa: poistumiskoodin ja mitä tahansa tiedostoja se jätti jälkeensä Lokirivit, konsolin värit, edistymistuloste: kaikki tuo on elävänä katsovaa ihmistä varten, eikä kello kahdelta yöllä kukaan ole Kiinnitä siis poistumiskoodien sanasto ennen kuin kosket rajapintaan, ja pidä se tylsänä

  • 0: jokainen tiedosto noudatti jokaista pyydettyä profiilia
  • 1: ainakin yksi tiedosto tuotti validointilöydöksiä
  • 2: työkalu itse epäonnistui ainakin yhdessä tiedostossa (vioittunut syöte, lukko, kaatuminen)

Ero koodien 1 ja 2 välillä on se, jonka tiimit ohittavat ja jota myöhemmin katuvat Vioittunut PDF, joka ei avaudu, ei ole validointivika Taita se koodiin 1, ja kuormallinen vaurioituneita skannauksia näkyy kojelaudoissasi äkillisenä vaatimustenmukaisuuden romahduksena, lähettäen jonkun jahtaamaan standardiregressiota, jota ei koskaan tapahtunut, kun todellinen tarina on rikkinäinen skanneri ylävirrassa

Kaksi muuta asiaa kuuluu sopimukseen Ensimmäinen on tiedostokohtainen aikakatkaisu Patologinen PDF, tuhansia sivuja syvästi sisäkkäisiä objektirakenteita, voi pitää yhtä validointiajoa kiinni minuutteja, eikä yöllisellä ikkunalla ole kärsivällisyyttä sille Tapa kyseisen tiedoston työ määräajassa, laske se työkaluvirheeksi ja pidä erä liikkeessä Toinen on karanteenihakemisto: siirrä jokainen aikakatkaistu tai avaamaton syöte sivuun sen sijaan, että jättäisit sen paikalleen Muutaman kuukauden aikana tuo hakemisto kerää hiljaa asiakkaidesi lähettämät pahimmat asiakirjat, ja tuo korpus on julkaisutestaukselle arvokkaampi kuin mikään käsin kirjoitettu synteettinen näyte

Kaavio poistumiskoodisopimuksesta Delphi-eräpreflight-CLI:lle, joka rakentuu PDFium Componentille, kartoittaen puhtaat ajot, validointilöydöt ja työkaluvirheet poistumiskoodeihin 0, 1 ja 2 levylle jääneiden JSON- ja HTML-raporttien rinnalla
Ajastin lukee vain poistumiskoodin ja jäljelle jääneet tiedostot, joten validointihavaintojen ja työkaluvirheiden on mapattava eri kooduihin

Standardien valinta, ja miksi vaatimustenmukaisuustaso on tärkeä

TPdfPreflightStandard-lueteltu tyyppi kattaa käytännössä esiintyvät perheet: ppsPdfA ISO 19005 -arkistointivaatimustenmukaisuudelle, ppsPdfUa ISO 14289 -esteettömyydelle, ppsPdfX painovaihdolle, sekä ppsPdfE, ppsPdfR ja ppsPdfVT suunnittelu-, rasteri- ja muuttuvan datan työlle Perheen sisällä moottori lukee asiakirjan väittämän vaatimustenmukaisuustason ja raportoi sen kutakin standardia kohti tuloksen ConformanceName-kentässä Perheen nimeäminen ei useinkaan riitä, koska taso on se, missä todellinen ero asuu PDF/A-2b lupaa visuaalisen toistettavuuden eikä mitään muuta PDF/A-3a lisää vaatimuksen loogisesta rakennetagituksesta ja sallii upotetut lähdetiedostot, mikä on paljon kovempi rima ylitettäväksi skannatulle materiaalille, jolla ei ole lainkaan tagipuuta Jos tämän saa väärin kumpaan suuntaan tahansa, erä valehtelee sinulle Jos säilytyskäytäntösi todella haluaa PDF/A-2b:tä, mutta hylkäät tiedostoja puuttuvien rakennetagien takia, raportti täyttyy löydöksistä, joita kukaan ei koskaan korjaa Hyväksy mikä tahansa PDF/A-merkintä tarkistamatta tasoa, ja hyväksyt asiakirjoja, jotka täyttävät heikomman riman kuin lupasit Valtion ostajien esteettömyysvaatimukset pinoavat yhä useammin PDF/UA:n kaiken tämän päälle, mikä ei lisää ajon kustannuksia lainkaan, koska BuildPdfPreflightReport (yksiköstä FPdfPreflightReport) ottaa vastaan joukon standardeja

Report := BuildPdfPreflightReport(Pdf, [ppsPdfA, ppsPdfUa]);

Yksi kutsu arvioi molemmat standardit ja antaa takaisin yhden konsolidoidun raporttitietueen

Miksi tyhjä löydöslista ei ole läpäisy

Raportti luetteloi löydökset standardeittain, ja tyhjä ongelmalista tarkoittaa vain "ongelmia ei löytynyt niistä standardeista, jotka oikeasti ajettiin" Se on suppeampi väite kuin "tiedosto noudattaa standardia, josta välität", ja näiden kahden välinen kuilu on paikka, jossa eräesitarkastus hiljaa mätänee Konfiguraatiokirjoitusvirhe, joka pudottaa ppsPdfA:n joukosta, tuottaa täsmälleen saman tyhjän ongelmalistan kuin aidosti puhdas tiedosto Kohtele siis hiljaisuutta epäilyttävänä Käy läpi Report.Results ja väitä kaksi asiaa jokaisesta standardista, jonka aioit tarkistaa: että sille on ylipäätään olemassa tulosmerkintä, ja että sen IsCompliant-lippu, jonka takana on Status = pfsPass, on tosi Yöllinen työ, joka rinnastaa "ei löydöksiä" tilaan "arkisto valmis" koskaan vahvistamatta, mitä standardeja arvioitiin, on klassinen tapa, jolla kansiollinen vaatimustenvastaisia tiedostoja purjehtii läpi kuukausia, kunnes ulkopuolinen auditoija avaa yhden veraPDF:llä ja koko arkisto joutuu kyseenalaiseksi

Toinen ansa piileskelee siinä, mitä löydös ylipäätään on Jokainen TPdfPreflightIssue kantaa Code-, Category-, Description- ja Recommendation-kentät, ja se nimeää rikotun säännön, ei sivua tai objektia Se on suunnitteluvalinta, jolla on seurauksia palautesilmukalle Raportti kertoo tuottavalle tiimille minkä luokan vika on olemassa, upottamaton fontti tai puuttuva XMP-tunniste, ja tietyn rikkovan objektin löytäminen on korjaustyökalun tehtävä alavirrassa, ei validoijan Rakenna raportin kuluttajasi vakaita Code-arvoja vasten, ei koskaan ihmisluettavaa kuvaustekstiä vasten, jota voidaan sanoittaa uudelleen julkaisujen välillä ilman varoitusta

Päätöskaavio, joka osoittaa miksi tyhjä PDFium Component preflight -löytöluettelo ei ole läpäisy Delphissä: jokainen pyydetty standardi tarvitsee tulosmerkinnän ja toden IsCompliant-lipun ennen kuin ajo on varmennettu läpäisy
Report.Results:n läpikäynti muuttaa hiljaisuuden tarkistetuksi tuomioksi: puuttuva standardimerkintä on konfiguraatiovirhe, ei puhdas tiedosto

Raporttitiedostot koneille ja päivystäjälle

Raporttitietue kirjoittaa samat löydökset viidessä muodossa: SaveJsonToFile, SaveCsvToFile, SaveHtmlToFile, SaveTextToFile ja SaveMarkdownToFile, kukin sopivalla ToJson-tyylisellä funktiolla, kun haluat merkkijonon muistiin levyn sijaan Vastusta houkutusta valita vain yksi Kirjoita JSON putkea varten, jotta CI voi liittää sen työtietueeseen ja jäsentää ongelmakoodit ja standardikohtaiset tilat raapimatta tekstiä Kirjoita HTML ihmiselle, joka hälytetään, koska se avautuu missä tahansa selaimessa ilman mitään työkaluja Nämä kaksi yhdessä maksavat yhden lisärivin per tiedosto ja säästävät päivystävän insinöörisi pahimmalta yksittäiseltä eräkäsittelyn tehtävältä, joka on raa'an JSON-blobin käänteismallinnus kello kahdelta yöllä selvittääkseen mikä tiedosto hajosi Yksi kuri on tärkeämpi kuin muodon valinta: johda jokainen raportin nimi syötetiedoston nimestä, ei koskaan aikaleimasta, tai kaksi rinnakkaista ajoa lomittaa raportteja, joita et enää voi yhdistää takaisin syötteisiinsä

Vakavuuskynnysten kuuluu olla konfiguraatiossa, ei koodissa Merkintä ilman vaihtoehtoista kuvausta on kova epäonnistuminen PDF/UA-lähetysportaalille ja ohitettava huomautus sisäiselle arkistolle, silti se on identtinen löydös molemmissa Paljasta epäonnistumistaso per profiili, jotta käytäntö voi muuttua ilman uudelleenkäännöstä, ja leimaa voimassa ollut taso itse työn yhteenvetoon Ensi vuosineljänneksellä kukaan ei muista, millä kynnyksellä lokakuun erä ajettiin, ja yhteenveto on ainoa paikka, jossa se muisti säilyy

Tiedostojen eristäminen niin, ettei yksi huono PDF voi upottaa erää

procedure RunPreflightBatch(const InputDir, ReportDir: string;
  out FilesWithFindings, ToolFailures: Integer);
var
  SR: TSearchRec;
  Pdf: TPdf;
  Report: TPdfPreflightReport;
begin
  FilesWithFindings := 0;
  ToolFailures := 0;
  if FindFirst(InputDir + '*.pdf', faAnyFile, SR) = 0 then
  try
    repeat
      Pdf := TPdf.Create(nil);   // uusi instanssi per tiedosto: ei tilan vuotoa
      try
        try
          Pdf.FileName := InputDir + SR.Name;
          Pdf.Active := True;
          if not Pdf.Active then  // latausvirheet ovat hiljaisia, eivät nosta poikkeusta
            raise EPdfError.Create('Cannot open ' + SR.Name);
          Report := BuildPdfPreflightReport(Pdf, [ppsPdfA, ppsPdfUa]);
          Report.SaveJsonToFile(ReportDir + ChangeFileExt(SR.Name, '.json'));
          Report.SaveHtmlToFile(ReportDir + ChangeFileExt(SR.Name, '.html'));
          if Report.TotalIssueCount > 0 then
            Inc(FilesWithFindings);
        except
          on E: Exception do
          begin
            Inc(ToolFailures);   // poistumiskoodi-2-aluetta, ei validointituomio
            WriteLn(ErrOutput, SR.Name + ': ' + E.Message);
          end;
        end;
      finally
        Pdf.Free;
      end;
    until FindNext(SR) <> 0;
  finally
    FindClose(SR);
  end;
end;

Kolme tarkoituksellista valintaa asuu tuossa silmukassa Tuore TPdf per tiedosto takaa, ettei yksi asiakirja, joka turmelee moottorin tilan, voi myrkyttää sitä seuraavia tiedostoja Eksplisiittinen Active-tarkistus ansaitsee paikkansa, koska Active := True nielaisee latausvirheet nostamatta niitä; jätä vartija pois, ja katkennut tiedosto ajautuu validointikutsuun asti ennen kuin se epäonnistuu jossain alavirrassa harhaanjohtavalla viestillä Sisempi try..except asuu tarkoituksella tiedostokohtaisen alueen sisällä, joten yksi poikkeus nostaa virhelaskuria ja silmukka jatkaa Haluat puhtaat raportit 4 999 hyvälle tiedostolle, vaikka tiedosto 5 000 olisi silppua Ja molemmat raporttimuodot kirjoitetaan levylle ennen kuin tuomio lasketaan yhteen, mikä tarkoittaa, että todisteet säilyvät, vaikka myöhempi bugi yhteenvetologiikassa laskisi väärin

Poistumiskoodin kartoitus supistuu sitten muutamaksi riviksi projektitiedostossa

Kaavio yhdestä PDFium Component preflight -tietueesta Delphissä tallennettuna JSON:na, CSV:nä, HTML:na, tekstinä ja Markdownina, nimet johdettuina syötetiedostosta ja fail-on-kynnys pidettynä konfiguraatiossa
JSON palvelee putkea ja HTML palvelee päivystävää ihmistä, kun taas syötteestä johdetut raporttinimet pitävät rinnakkaiset ajot täsmäytettävinä
begin
  RunPreflightBatch(ParamStr(1), ParamStr(2), Findings, Failures);
  if Failures > 0 then
    Halt(2)
  else if Findings > 0 then
    Halt(1);
  // läpi pudotessaan poistuu koodilla 0: jokainen tiedosto noudatti vaatimuksia
end.

Mitä esitarkastus ei tee puolestasi

Moottori havaitsee; se ei korjaa Löydös upottamattomasta fontista tai laiteriippuvaisesta väriavaruudesta on työmääräys sille, joka tuottaa tiedostot, eikä validoijalla ole keinoa paikata sitä paikan päällä Suunnittele siis palautesilmukka tarkoituksella Raporttien on laskeuduttava sinne, missä tuottava tiimi oikeasti lukee niitä, tai samat löydökset ilmestyvät uudelleen joka yö, kunnes joku lopulta kysyy, miksi vaatimustenmukaisuusaste ei koskaan parane Kannattaa myös ristiintarkistaa otos tuomioista riippumatonta validoijaa vasten, veraPDF PDF/A:lle tai Acrobatin esitarkastus PDF/X:lle, ennen kuin ulkopuolinen auditoija ristiintarkistaa ne puolestasi Kun kaksi moottoria ovat eri mieltä todellisesta asiakastiedostosta, tuo asiakirja ei ole harmi; se on täsmälleen se regressiotapaus, joka julkaisutestauksestasi puuttui Säilytä se, nimeä se, ja aja se jokaisessa käännöksessä

Vielä yksi pari on hyvä tietää Sama validointimoottori ohjaa vuorovaikutteisia tarkistuksia arviointikäyttöliittymässä, joten tämä pääton CLI ja analyytikoille suunnattu PDF-vastaanoton arviointityöpöytä voivat jakaa yhden validointisanaston ajautumatta erilleen ajan myötä Ja koska [ppsPdfA, ppsPdfUa] arvioi esteettömyyden samalla ajolla, erän PDF/UA-puoli asettuu siististi linjaan katseluohjelmapuolen työn, kuten esteettömän PDF-lukijan rakentaminen Delphissä, kanssa Profiilit, raporttimuodot ja koko esitarkastusrajapinta on dokumentoitu PDFium Component -tuotesivulla