Teknisk artikel

Konvertera en PDF till PDF/A och reparera dess metadata

ConvertToPDFA förvandlar ett vanligt dokument till ett arkivdokument i ett enda anrop: det tar bort vad den valda delen förbjuder, lägger till vad delen kräver, anger den del dokumentet gör anspråk på och kontrollerar sedan resultatet. Anspråket rapporteras som uppfyllt först när kontrollen godkänns, och GetPDFAConversionReport listar vad som gjordes och vad som fortfarande står i vägen

Den sista egenskapen är det desigbeslut som är värt att dröja vid. En konverterare som stämplar anspråket utan att kontrollera är värre än ingen konverterare alls, eftersom en fil som påstår sig vara arkivbar och inte är det passerar rakt igenom de mycket system som annars skulle ha fångat den. Felet ytor år senare, i en revision, på ett dokument ingen kan återskapa

Varför misslyckas en giltigt utseende PDF med en PDF/A-kontroll?

Oftast för att de två ställena en PDF säger vem som skrev den inte stämmer överens. En validator läser både dokumentets informationsordbok och XMP-paketet och förkastar en fil där de skiljer sig — och de flesta filer som misslyckas på den punkten hade helt enkelt aldrig XMP-halvan skriven alls

RepairDocumentMetadata för dem till överensstämmelse och returnerar hur många poster den reparerade. Där bara ena halvan bär ett värde fylls den andra från den, så ingenting som redan registrerats kastas bort. Ingen behöver besluta vilken kopia som är auktoritativ, eftersom en kopia i praktiken är tom

Det finns en andra reparation i samma anrop som fångar ett subtilare fall. Ett dokument satt till ett PDF/A-läge får sin standardidentifiering återställd om den gått förlorad, vilket händer när en anropare tillhandahåller ett eget XMP-paket. Utan den identifieringen läser en validator filen som en vanlig PDF och rapporterar varje regel i den anspråkade delen som ouppfylld — en spektakulärt utseende misslyckande med en liten orsak

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;

Välja delen innan du konverterar

SetPDFAMode och ConvertToPDFA delar samma numrering av lägen, och tre av värdena är nylagna. Läge 9 är PDF/A-4, delen byggd på PDF 2.0. Läge 10 är PDF/A-4e, som dessutom tillåter 3D och rich media, och läge 11 är PDF/A-4f, som tillåter en inbäddad fil av valfritt format

Del 4 identifierar sig annorlunda än delarna före den: genom delnummer och året dess del publicerades, utan överensstämmelsebrev för vanlig PDF/A-4 och med bokstaven E eller F för de två tilläggen. Kontrollen känner igen del 4, bedömer dess filer mot PDF 2.0 i stället för 1.7, och rapporterar en del 4-fil som inte anger sitt revisionsår

Varje inbäddad fil i ett del 4-dokument anger hur den relaterar till dokumentet, vilket både del 3 och 4 kräver. Det är regeln som brukade fånga vanliga bilagor: relationen skrevs bara för bilagor efter den första och aldrig för den sista, så ett dokument med en enda bilaga — det vanliga fallet — bar ingen alls och misslyckades med validering på just den punkten

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;

Vad konverteringsrapporten är till för

Att besluta vad du ska göra härnäst. En konvertering som lyckas behöver ingen rapport; en konvertering som inte gör det är hela anledningen till att rapporten finns. Vissa hinder är avlägsningsbara av en konverterare och andra är det inte — kryptering, förbjudet innehåll som bär betydelse, ett teckensnittsprogram som helt enkelt inte finns någonstans på maskinen. Rapporten skiljer vad som gjordes från vad som återstår, vilket förvandlar "konvertering misslyckades" till en arbetspost

Behandla utslaget som porten i ett batch-flöde. Konvertera, läs utslaget och dirigera filen: arkivera de som godkändes, köa resten för en människa med rapporten bifogad. Vad du inte bör göra är att spara utdata från en misslyckad konvertering i arkivet för att den ser bättre ut än indata — den bär nu ett anspråk som kontrollen vägrade att bekräfta

Läsa märket en fil redan bär

Innan du konverterar någonting, veta vad dokumentet säger om sig självt. En PDF/A-kontroll som inte kan läsa det befintliga standardmärket bedömer varje fil mot del 1 vad den än deklarerar, vilket betyder att ett fullgiltigt PDF/A-2- eller PDF/A-3-dokument rapporteras som att bära inget märke och som att vara av för hög version — motsatsen till sanningen

Märket läses oavsett om producenten skrev det som ett XMP-element eller som ett attribut. Båda formerna är vanlig XMP, och att acceptera bara en av dem lämnar filer från andra producenter som ser omarkerade ut. Om du någonsin undrat varför ett dokument som validerar annorstädes misslyckas i ditt eget flöde är detta en bra plats att titta först

Sanera innan arkivering och felet som är värt att känna till

Arkivkonvertering och sanering körs ofta tillsammans, eftersom det innehåll en säkerhetspolicy vill ta bort överlappar kraftigt med det innehåll PDF/A förbjuder. SanitizeDocument tar bort JavaScript, och att ta bort det sista skriptet tar också bort det tomma namnträdet det lämnar efter sig — ett träd som annars fortfarande skulle berätta för en läsare att dokumentet bar skript

Den andra halvan lärdes på det hårda sättet: en off-by-one i paketlistan betydde att sanering rapporterade att den tog bort skript medan den tog bort inga, så ett dokument som hade sanerats körde fortfarande sina skript när det öppnades. Det är ett bra argument för den allmänna princip som hela den här artikeln vilar på — verifiera resultatet i stället för att lita på operationen, i ditt eget flöde lika mycket som i biblioteket

För det omgivande arkivarbetet, se genomgångarna av PDF/A- och PDF/UA-preflight, äkta redigering och innehållsborttagning och PDF/A-3 XMP-tilläggsscheman för Factur-X, som täcker metadatasidan när det arkiverade dokumentet också bär strukturerade fakturadata

PDFlibPas är ett inbyggt Pascal PDF-bibliotek för Delphi, C++Builder och Lazarus, så konvertering, reparation och validering sker alla inuti din egen process utan externt verktyg i kedjan — se PDFlibPas produktsida för de PDF/A-delar och plattformar som stöds