PDF/A en PDF/UA beantwoorden twee vragen die niets met elkaar te maken hebben, en ze behandelen als één enkele toegankelijkheids- en archiveringscheckbox is precies hoe kapotte bestanden een archief bereiken met een compliancelabel om. PDF/A vraagt of een bestand over twintig jaar nog steeds getrouw rendert. PDF/UA vraagt of hulptechnologie het vandaag kan lezen. Een document kan het ene glansloos doorstaan en het andere laten falen, dus het enige eerlijke oordeel komt voort uit het draaien van beide, en uit het draaien ervan voordat het bestand wordt weggeschreven, niet nadat een downstreamsysteem de conformance-identificator vertrouwt die in zijn metadata is ingebakken. Die identificator is een zelfverklaring. Niets in het formaat vereist dat hij klopt, en een applicatie die "PDF/A-1b" in de XMP schrijft zonder tegen de standaard te valideren, produceert een bestand dat compliant lijkt voor elke consument die alleen het label leest. losLab PDF Library (PDF Library for Delphi) sluit die kloof voor Delphi en C++Builder door beide validators in de bibliotheek in te bouwen, zodat de controle in-process draait zonder dat een externe service opgezet hoeft te worden
Twee standaarden die bestanden om tegengestelde redenen laten falen
ISO 19005 (PDF/A) is een reproductiecontract. Een conform bestand moet tientallen jaren later identiek renderen op software die het systeem dat het produceerde nooit heeft gezien, dus de regels pakken externe afhankelijkheden aan: elk lettertype ingebed, kleur verankerd aan een ingebedde ICC-OutputIntent of uitgedrukt in een apparaatonafhankelijke ruimte, geen versleuteling in PDF/A-1, geen JavaScript, XMP-metadata die overeenkomt met de documentinformatiewoordenlijst. ISO 14289 (PDF/UA) is daarentegen een semantiekcontract. Hulptechnologie moet het document doorlopen en er met betekenis uit komen, die in een volledig andere laag leeft: een volledige structuurboom, alternatieve tekst bij figuren, een documenttitel ingesteld voor weergave, kopniveaus die niet overslaan, tabelkoprelaties die overleven zodra de pagina van het scherm is
Omdat de twee standaarden verschillende lagen bewaken, zijn de bestanden die u bijten degene die ertussenin zitten. Een archiefperfect document kan stil zijn voor een schermlezer. Een prachtig getagd document kan verwijzen naar een desktop-lettertype dat over tien jaar niet meer bestaat. Public-sector-uitgeverij is de gebruikelijke plek waar beide eisen tegelijk landen, en een pipeline daar kan ze niet samenvoegen tot één enkele poort. De bevindingen gaan naar verschillende mensen. Niet-ingbedde lettertypen zijn een defect in de code die de PDF genereert, terwijl ontbrekende alternatieve tekst toebehoort aan wie de contentsjablonen beheert, en een rapport dat de twee mengt wordt gewoon twee keer doorgestuurd
Welk deel van PDF/A u richt, doet er evenveel toe als of u het haalt. PDF/A-1 is bevroren op PDF 1.4 en wijst transparantie en JPEG2000 af, allebei waar modern rapportage-output zonder nadenken naar grijpt. PDF/A-2 (ISO 19005-2, gebouwd op ISO 32000-1) accepteert beide en is de verstandige standaardkeuze voor een nieuw archief. PDF/A-3 gaat verder en staat ingebedde bestanden van elk type toe, waarop gereguleerde e-facturatieformaten leunen. Een team dat in 2026 nog steeds op PDF/A-1b standaardiseert, draagt meestal een eis mee die iemand vijftien jaar geleden schreef, en de target-part heronderhandelen is vaak goedkoper dan transparantie uit elke grafiek die het systeem uitspuwt strippen
Gestructureerde bevindingen tijdens inname
Het flat-API-toegangspunt is CheckFileCompliance, met de testselector 1 voor PDF/A en 2 voor PDF/UA. Het geeft een string-list-handle terug waarvan de items afzonderlijke bevindingen zijn, één per regel, precies de vorm die een geautomatiseerde poort wil doorlopen:
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 betekent "geen bevindingen" OF "bestand onleesbaar" -- maak dat onderscheid voordat je doorgeeft
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;
Twee details bepalen of dit onbemand draait. De eerste is een returnwaarde die twee tegengestelde dingen betekent. CheckFileCompliance retourneert 0 wanneer het bestand volledig compliant is en ook wanneer het bestand helemaal niet geopend kon worden, omdat intern een lege resultatenlijst in beide gevallen instort tot 0. Een poort die 0 als een slagingsresultaat leest, wuift corrupte uploads rechtstreeks het archief in, dus maak het ondubbelzinnig met LastErrorCode voordat u de nul vertrouwt, zoals de poort hierboven doet. De tweede betreft waar het bestand zich in zijn levenscyclus bevindt. De checker draait op de streaming-reader van de bibliotheek in plaats van op het volledige documentmodel, opent het bestand direct met read-sharing en roept nooit LoadFromFile aan, wat de reden is dat het multi-gigabyte-input kan verwerken zonder een objectboom te bouwen. Diezelfde streaming-open faalt terwijl een ander proces het bestand nog voor schrijven vasthoudt, en een upload in uitvoering is precies die toestand. Zet de poort pas nadat de overdracht is afgerond
Het streaming-ontwerp betaalt zich onder load opnieuw uit. Elke controle opent zijn input read-only en deelt hem voor lezen, zodat een corpus-audit uitschaalt over worker-threads of processen met één TPDFlib-instantie per worker en geen contentie ertussen. De resource die discipline nodig heeft is de handle zelf. Elk resultaat verschillend van nul van CheckFileCompliance blijft toegewezen totdat u ReleaseStringList aanroept, en een langlopende poort die vergeet ze vrij te geven crasht niet, maar lekt gewoon langzaam geheugen totdat iemand op zoek gaat naar waarom
Rapporten voor mensen, diffs voor build-poorten
Een bevindingenlijst is de juiste vorm voor een poort en de verkeerde vorm voor een e-mail naar het sjabloonteam. CreatePreflightReport rendert dezelfde analyse als leesbare prosa, CreatePreflightReportEx voegt een rapportformaatselector toe, en SavePreflightReport schrijft het naar schijf zodat het rapport kan meereizen binnen het geleverde documentpakket. Tal van archiefcontracten maken dat rapport een opleverbaar product op zich, niet alleen een intern artefact
Het familielid dat zijn plaats stilverdiend opeist is ComparePreflightReports. Compliance is een regressievlak zoals elk ander stuk gedrag. Een sjabloon-aanpassing, een nieuw gelicentieerd huislettertype of een bibliotheekupgrade kan elk een bevinding introduceren die er bij de vorige release niet was, en geen van hen kondigt zichzelf aan. Houd golden reports voor een set representatieve documenten onder versiebeheer, regenereer ze na elke wijziging, en draai ComparePreflightReports om de delta te berekenen. Een lege diff is een release-artefact dat het bewaren waard is. Een onverwachte bevinding laat de build falen, wat een veel goedkopere plek is om het te ontdekken dan de audit
Output genereren die bij de eerste run slaagt
Preflight verdient zijn kost op bestanden die van elders komen. Voor documenten die uw eigen code produceert, is het na generatie overtredingen vinden en ze terug inpatchen de trage omweg. PDF Library for Delphi draagt een generation-side modus voor elke standaard, en u kunt beide inschakelen voor hetzelfde document:
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: verplicht voor PDF/UA
// ... teken hier de getagde content ...
Diag := Pdf.GetPDFUADiagnostics;
if Diag <> '' then
Writeln('fix before shipping: ', Diag);
Pdf.SaveToFile('statement.pdf');
// de preflight die telt draait op het opgeslagen bestand:
Writeln(Pdf.CreatePreflightReport('statement.pdf', '', 1, 0));
finally
Pdf.Free;
end;
end;
De val zit op save-tijd. Verschillende conformance-reparaties gebeuren terwijl het document wordt geserialiseerd in plaats van wanneer u de modus inschakelt: de print-vlag op annotaties forceren, de standaard AFRelationship voor ingebedde PDF/A-3-bestanden schrijven, tab-volgorde en formulierveldbeschrijvingen normaliseren voor PDF/UA. Het document dat in het geheugen staat is niet byte-identiek aan het document dat op schijf belandt, dus het enige preflight-oordeel dat iets betekent is het oordeel dat berekend is vanuit het opgeslagen bestand. Valideer statement.pdf zelf. Leid geen compliance af uit het object dat nog in het geheugen staat, omdat de bytes die u zou beoordelen niet de bytes zijn die u leverde
Facturatiescenario's die machineleesbare XML meedragen naast het visuele document volgen het ZUGFeRD- en Factur-X-patroon, dat op PDF/A-3 gebouwd is. Die moeten de bijlagerelatie expliciet instellen met SetPDFA3DefaultAFRelationship, aangezien ISO 19005-3 vereist dat elk ingebed bestand zijn rol ten opzichte van het document declareert. Laat het oningesteld en de ingebedde XML is slechts een blob zonder vermeld doel, wat de validator opmerkt
Onafhankelijke scheidsrechters: veraPDF en Acrobat
Een producent zou niet de enige rechter van zijn eigen output moeten zijn. De PDF Library for Delphi-checkers geven u snelle, gestructureerde oordelen in-process, wat u op het hot-path wilt, maar de release-poort voor een archiefbatch moet de output nog steeds door een validator halen die niemand in uw team geschreven heeft. veraPDF is de door de community onderhouden referentie-implementatie voor PDF/A en de tool die de meeste archieven in hun acceptatiecriteria noemen, dus dat is degene om mee te matchen. Acrobats preflight-profielen maken een nuttige beslisser wanneer veraPDF en de in-process-controle van mening verschillen. Leg de validatornaam en zijn versie vast naast elk opgeslagen rapport. Een bewering dat een bestand veraPDF doorstond zegt heel weinig zonder het build-nummer dat het doorstond, aangezien de tool zijn regels tussen releases aanscherpt
Validators verschillen inderdaad van mening aan de randen van de standaarden, en als ze dat doen is het antwoord niet om de tool te kiezen die u leuk vindt. Verklein het bestand tot een minimaal voorbeeld dat nog steeds de onenigheid uitlokt en lees het tegen de standaardtekst. Een uur daarmee brengt meestal een van twee dingen aan het licht: een echte tool-bug die het waard is upstream te melden, of een clausule die uw team verkeerd heeft gelezen en die u zou moeten opschrijven in de compliance-notities zodat de volgende persoon het niet heroverweegt
Versleutelde input krijgt een snelkoppeling. Beide checkers nemen een wachtwoordargument, maar een PDF/A-1-bestand met een encryptie-woordenlijst is al niet-conform, omdat ISO 19005-1 versleuteling ronduit verbiedt, dus een versleutelde inzending kan worden afgewezen voordat enige diepere analyse draait. Uitzoeken wat een encryptie-woordenlijst daadwerkelijk toekent is een eigen taak, behandeld in het auditen van PDF-versleuteling en rechten
PDF/UA-bevindingen herleiden bijna altijd naar hoe de structuurboom in de eerste plaats is opgesteld, en de tagging-technieken daarachter staan in het bouwen van getagde PDF-structuurbomen in Delphi. Archieven die ook digitale handtekeningen eisen, zouden deze poort moeten paaren met de workflow in PAdES-ondertekening en -validatie. De volledige preflight-API-referentie staat op de losLab PDF Library voor Delphi-productpagina