PDFlibPas kači ugrađenu datoteku na jednu konkretnu stranu, a ne na dokument kao celinu, tako što upisuje /AF niz u rečnik stranice dok sam payload ostaje evidentiran u EmbeddedFiles name stablu dokumenta. Ta podela je ono što ISO 32000-2 §14.13 opisuje, i upravo ona čitaču daje odgovor na pitanje koje prilog na nivou dokumenta ne može da da: kojoj strani ovi podaci pripadaju
Slučajevi upotrebe su konkretniji od opštih priloga. Izveštaj o premeru gde svaka strana nosi sirove serije merenja iza svog grafikona. Skeniran paket gde svaka strana čuva OCR rezultat koji je proizveo njen tekstualni sloj. Zbirka crteža gde svaki list nosi CAD izvod iz kojeg je renderovan. U svakom od tih slučajeva spisak priloga na nivou dokumenta bio bi gomila datoteka čija imena u sebi nose brojeve strana, a to je konvencija, ne struktura
Jedan payload, dva mesta sa kojih se na njega referencira
Ključna strukturna tačka je da povezanost na nivou strane ne pravi drugi primerak ičega. Datoteka se ugrađuje jednom i evidentira u EmbeddedFiles name stablu potpuno isto kao prilog na nivou dokumenta, koristeći isti mehanizam file specification-a. Razlika je u tome gde se upisuju referenca i njen ključ odnosa: u rečnik stranice umesto u katalog dokumenta
Iz toga slede dve posledice. Prvo, čitač koji zna samo za priloge na nivou dokumenta i dalje nalazi payload, jer se on nalazi u name stablu gde takav čitač traži. Drugo, brisanje povezanosti stranice uklanja vezu, a ne datoteku. ClearPageAssociatedFiles otkačuje stranu od njenih povezanih datoteka i ostavlja payload-e dostižnim kroz name stablo, a to je konzervativno ponašanje: operacija koja kaže obriši povezanost ne sme tiho da uništi podatke na koje drugi deo dokumenta možda referencira
Ta funkcija ima jedan namerno uzan uslov za uspeh koji vredi znati. Uspeh prijavljuje samo kad stranica stvarno nosi /AF ključ. Stranica koja nikada nije imala povezanosti vraća neuspeh umesto vesele potvrde, pa pozivalac ne može no-op da uzme za završeno čišćenje
var
Lib: TPDFlib;
Idx, I: Integer;
begin
Lib := TPDFlib.Create(nil);
try
Lib.LoadFromFile('survey-report.pdf');
// Kači seriju merenja koja je proizvela grafikon na strani 3
Idx := Lib.AddPageAssociatedFileFromFile(3,
'series-03.csv', // datoteka na disku
'measurements.csv', // ime za prikaz unutar PDF-a
'text/csv', // MIME tip
'Raw measurement series for figure 3',
'Data'); // AFRelationship, ISO 32000-2 14.13
if Idx < 0 then
raise Exception.Create('page association refused');
for I := 0 to Lib.GetPageAssociatedFileCount(3) - 1 do
Writeln('page 3 associated file, embedded index ',
Lib.GetPageAssociatedFileEmbeddedIndex(3, I));
Lib.SaveToFile('survey-report-with-data.pdf');
finally
Lib.Free;
end;
end;
String odnosa u praksi nije slobodan tekst. ISO 32000-2 definiše vokabular, Source, Data, Alternative, Supplement, EncryptedPayload, FormData, Schema i Unspecified, i potrošači se oslanjaju na njega. Data za brojeve iza grafikona, Source za dokument iz kojeg je stranica generisana, Alternative za ekvivalentan prikaz. Birajte iz vokabulara i kad još ništa u vašem pipeline-u ne čita taj ključ, jer sledeća alatka u lancu možda hoće
Zašto isto traženje treba FollowRef u oba smera?
Zato što praćenje referenci odgovara na dva različita pitanja, i kod mora da zna koje od njih postavlje. Traženje ključa koje prati indirektne reference vraća objekat na koji referenca pokazuje. Traženje koje ne prati vraća samu referencu. Oba su ispravna, a pogrešan izbor proizvodi tiho pogrešno ponašanje umesto grešku
Čitanje povezane datoteke pokazuje prvi smer. Da biste dobili broj objekta ugrađenog toka iza /EF i /F ključeva file specification-a, traženje ne sme da prati, jer praćenje razrešuje referencu u sam objekat toka i broj objekta nestaje. Pravilo se generališe: svaki kod koji treba identitet objekta, a ne njegov sadržaj, mora da uzme sirovu referencu
Optional content pokazuje suprotan smer, i taj je koštao više da se pronađe. Rečnik svojstava optional content-a upisuje se u katalog kao indirektan objekat, pa kod koji ga čita nazad bez praćenja dobija referencu umesto rečnika. Provera tipa na toj vrednosti tada pada, i prirodna fallback grana — ako konfiguracije nema, napravi je — proradi i prepiše konfiguraciju koja je već tamo stajala. Ništa ne baca izuzetak. Slojevi opisani u optional content grupama i slojevima jednostavno izgube svoje podrazumevano stanje vidljivosti
Lekcija se generališe van oba slučaja. Kad traženje može da vrati ili referencu ili objekat, gola provera tipa nije obrada greške: to je grana koja će jednom biti uzeta iz pogrešnog razloga. Odlučite eksplicitno šta svako mesto poziva treba i dajte prednost javnom API-ju koji na pitanje odgovara direktno, poput svojstva koja broji optional content grupe, umesto da zadirate u zaštićen pristupnik za katalog rečnik
// Prilozi na nivou dokumenta i povezanosti na nivou strane koegzistiraju.
// Ugrađena datoteka može biti označena i kao povezana na nivou dokumenta
if Lib.IsEmbeddedFileAssociated(0) = 0 then
Lib.SetEmbeddedFileAssociated(0, 1, 'Supplement');
Writeln('document associated files: ', Lib.GetAssociatedFileCount);
Writeln('page 3 associated files : ',
Lib.GetPageAssociatedFileCount(3));
// Brisanje otkačuje vezu stranice; payload ostaje u name stablu
if Lib.ClearPageAssociatedFiles(3) > 0 then
Writeln('page 3 associations removed, payloads still reachable');
Šta conformance režimi rade prilozima
Arhivski profili ograničavaju šta sme da se ugradi, i to ograničenje se sprovodi na ulaznoj tački, a ne u trenutku čuvanja. PDF/A-1 ugrađene datoteke zabranjuje u potpunosti, PDF/A-2 dopušta samo ugrađene PDF/A dokumente, a PDF/A-3 je profil koji je ugrađivanje otvorio za proizvoljne tipove datoteka, i upravo zato hibridni formati faktura počivaju na njemu
PDFlibPas odbija prilog kad ga aktivni conformance režim ne dopušta, na samom pozivu, a ne stotine operacija kasnije tokom izlaza. To je namerna odluka o tome gde je grešku najjeftinije obraditi: odbijanje na mestu poziva imenuje datoteku koju ste dodavali, dok odbijanje pri čuvanju imenuje dokument i ostavlja vas da ishodujete koji od četrdeset priloga je kriv
Zato se povezane datoteke i pojavljuju toliko često u elektronskom fakturisanju. Hibridna faktura je PDF koji čovek čita, sa mašinski čitljivim XML payload-om zakačenim i označenim pravim odnosom, i profil kontejnera i ključ odnosa deo su specifikacije, a ne konvencije. Ta konstrukcija je obrađena u članku o izgradnji Factur-X i ZUGFeRD hibridnih faktura, a metapodaci u PDF/A-3 XMP extension šemi
Kada povezanost treba da bude po strani, a ne po dokumentu?
Kad potrošač treba da zna kojoj strani podaci pripadaju, i samo tada. Prilozi na nivou dokumenta su jednostavniji, šire podržani od pregledača i dovoljni kad god payload opisuje ceo dokument: XML fakture, manifest potpisa, arhiva izvora. Do povezanosti na nivou strane posežite kad je payload zaista opsegom vezan za stranu i kad je identitet strane deo njegovog značenja
Podrška je praktično ograničenje. Datoteke povezane na nivou strane su konstrukcija iz PDF 2.0, i podrška u pregledačima je tanja nego za priloge na nivou dokumenta. Pošto payload u svakom slučaju sedi u name stablu, pregledač koji ignoriše /AF na stranama i dalje prikazuje datoteku u spisku priloga, pa propadanje ide blago. Ali ako je veza sa stranom suštinska za vašeg potrošača, a ne koristan metapodatak, proverite čitač kog stvarno targetirate umesto da pretpostavljate
Datoteke povezane na nivou strane, prilozi na nivou dokumenta i arhivsko-profilna vrata koja upravljaju obojim stižu uz PDFlibPas Delphi PDF biblioteku. Ako pri ulazu istovremeno i popravljate starije datoteke, rad na metapodacima i conformance-u iz konverzije u PDF/A uz popravku metapodataka je ono što odlučuje koja je od ovih putanja za priloge vama uopšte dostupna