PDFlibPas įdėtąjį failą prikabina prie vieno konkretaus puslapio, o ne prie viso dokumento: į puslapio žodyną įrašo /AF masyvą, o pats turinys lieka registruotas dokumento EmbeddedFiles vardų medyje. Būtent tą suskaidymą aprašo ISO 32000-2 §14.13, ir būtent jis leidžia skaitytojui atsakyti į klausimą, į kurį dokumento lygio priedas neatsako: kuriam puslapiui šie duomenys priklauso
Naudojimo atvejai specifiškesni nei bendrieji priedai. Apklausos ataskaita, kurioje kiekvienas puslapis neša žaliąją matavimų eilutę, pagal kurią nupieštas jo grafikas. Skenuotas paketas, kuriame kiekvienas puslapis laiko OCR rezultatą, iš kurio atsirado jo teksto sluoksnis. Brėžinių rinkinys, kuriame kiekvienas lapas neša CAD ištrauką, iš kurios jis atvaizduotas. Kiekvienu atveju dokumento lygio priedų sąrašas būtų krūva failų, kurių vardai užkoduoja puslapių numerius — tai konvencija, o ne struktūra
Vienas turinys, dvi vietos, iš kurių jis nurodomas
Svarbiausias struktūrinis dalykas: puslapio lygio susiejimas nesukuria nieko antros kopijos. Failas įdedamas vieną kartą ir užregistruojamas EmbeddedFiles vardų medyje tiksliai taip, kaip dokumento lygio priedas, naudojant tą pačią failo specifikacijos techniką. Skiriasi tik tai, kur įrašoma nuoroda ir jos santykio raktas: į puslapio žodyną vietoje dokumento katalogo
Iš to seka du padariniai. Pirma, skaitytojas, kuris žino tik apie dokumento lygio priedus, vis tiek suras turinį, nes jis yra vardų medyje, kur toks skaitytojas ir žiūri. Antra, puslapio susiejimo išvalymas pašalina susietį, o ne failą. ClearPageAssociatedFiles atkabina puslapį nuo jo susietųjų failų ir palieka turinius pasiekiamus per vardų medį — tai konservatyvi elgsena: operacija, kuri sako išvalyti susiejimą, neturi tyčiomis naikinti duomenų, į kuriuos gali rodyti kita dokumento dalis
Ta funkcija turi vieną sąmoningai siaurą sėkmės sąlygą, vertą žinoti. Sėkmę ji praneša tik tada, kai puslapis iš tikrųjų nešė /AF raktą. Puslapis, kuris niekada neturėjo susiejimų, grąžina nesėkmę, o ne linksmą patvirtinimą, todėl kviečiančioji pusė negali nieko nedarančio veiksmo palaikyti baigtu išvalymu
var
Lib: TPDFlib;
Idx, I: Integer;
begin
Lib := TPDFlib.Create(nil);
try
Lib.LoadFromFile('survey-report.pdf');
// Prikabinkite matavimų eilutę, iš kurios atsirado 3 puslapio grafikas
Idx := Lib.AddPageAssociatedFileFromFile(3,
'series-03.csv', // failas diske
'measurements.csv', // rodomas vardas PDF viduje
'text/csv', // MIME tipas
'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;
Santykio eilutė praktikoje nėra laisvas tekstas. ISO 32000-2 apibrėžia žodyną — Source, Data, Alternative, Supplement, EncryptedPayload, FormData, Schema ir Unspecified, — ir vartotojai remiasi juo. Data skaičiams už grafiko, Source dokumentui, iš kurio puslapis sugeneruotas, Alternative lygiavertei atmainai. Rinkitės iš to žodyno net tada, kai jūsų konvejeryje jo kol kas neskaito niekas, nes grandinėje sekantis įrankis gali skaityti
Kodėl tas pats paieškos veiksmas abiem kryptimis reikalauja FollowRef?
Todėl, kad nuorodų sekimas atsako į du skirtingus klausimus, ir kodas turi žinoti, kurį iš jų klausia. Rakto paieška, sekdama netiesiogines nuorodas, grąžina objektą, į kurį nuoroda rodo. Paieška, kuria neseka, grąžina pačią nuorodą. Abi teisingos, o netinkamos naudojimas duoda tylų neteisingą elgesį, o ne klaidą
Susieto failo skaitymas pademonstruoja pirmą kryptį. Norint gauti įdėtojo srauto, slepiančio už failo specifikacijos /EF ir /F raktų, objekto numerį, paieška neturi sekti, nes sekimas nuorodą išspręndžia į srauto objektą ir objekto numerio nebėra. Taisyklė apibendrinama: bet kuris kodo kelias, kuriam reikia objekto tapatybės, o ne objekto turinio, turi imti žaliąją nuorodą
Pasirinktinas turinys rodo priešingą kryptį, ir jo paieška kainavo daugiau. Pasirinktino turinio savybių žodynas į katalogą įrašomas kaip netiesioginis objektas, todėl kodas, skaitantis jį atgal nesekdamas, gauna nuorodą, o ne žodyną. Tipų patikra tos reikšmės tada žlunga, ir natūrali atsarginė šaka — jei konfigūracijos nėra, sukurti — įsijungia ir perrašo ten jau buvusią konfigūraciją. Niekas nepakelia klaidos. Sluoksniai, aprašyti straipsnyje pasirinktino turinio grupės ir sluoksniai, tiesiog praranda savo numatytąją matomumo būseną
Pamoka apibendrina abu atvejus. Kai paieška gali grąžinti ir nuorodą, ir objektą, plika tipų patikra nėra klaidų apdorojimas: tai šaka, kuri anksčiau ar vėliau bus pasirinkta dėl netinkamos priežasties. Aiškiai nuspręskite, ko reikia kiekvienai iškvietimo vietai, ir teikite pirmenybę viešajam API, kuris atsako į klausimą tiesiogiai, pavyzdžiui, pasirinktino turinio skaičiaus savybei, o ne skverbimuisi į apsaugotą prieigą prie katalogo žodyno
// Dokumentinio lygio priedai ir puslapio lygio susiejimai egzistuoja kartu.
// Įdėtąjį failą galima pažymėti susietu ir dokumento lygiu
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));
// Išvalymas atkabina puslapio susietį; turinys lieka vardų medyje
if Lib.ClearPageAssociatedFiles(3) > 0 then
Writeln('page 3 associations removed, payloads still reachable');
Ką prie priedų daro suderinamumo režimai
Archyviniai profiliai riboja, ką galima įdėti, ir apribojimas vykdomas įėjimo taške, o ne išsaugojimo metu. PDF/A-1 draudžia įdėtuosius failus visiškai, PDF/A-2 leidžia tik įdėtuosius PDF/A dokumentus, o PDF/A-3 yra profilis, atvėręs įdėjimą savavalėms failų rūšims — būtent todėl ant jo ir statomi hibridiniai sąskaitų formatai
PDFlibPas atmeta priedą, kai aktyvus suderinamumo režimas jo neleidžia, — iškvietimo metu, o ne šimtus operacijų vėliau, išvesties metu. Tai sąmoningas pasirinkimas, kur klaidos atžvilgiu pigiausia reaguoti: atmetimas iškvietimo vietoje įvardija failą, kurį įdėjote, o atmetimas išsaugojimo metu įvardija dokumentą ir palieka jums išsiaiškinti, kuris iš keturiasdešimties priedų to kaltas
Todėl susietieji failai elektroninėse sąskaitose ir atsiranda taip dažnai. Hibridinė sąskaita yra PDF, kurį skaito žmogus, su prie jo prikabintu ir tinkamu santykiu pažymėtu mašininai skaitomu XML turiniu, ir konteinerio profilis, ir santykio raktas yra specifikacijos dalis, o ne konvencijos. Ta konstrukcija aprašyta straipsnyje Factur-X ir ZUGFeRD hibridinių sąskaitų kūrimas, o metaduomenų pusė — straipsnyje PDF/A-3 XMP plėtinio schema
Kada susiejimas turi būti puslapiui, o ne dokumentui?
Kai vartotojui reikia žinoti, kuriam puslapiui duomenys priklauso — ir tik tada. Dokumento lygio priedai paprastesni, plačiau palaikomi peržiūros programų ir pakankami, kai turinys apibūdina visą dokumentą: sąskaitos XML, parašo manifestas, pirminio kodo archyvas. Prie puslapio lygio susiejimo imkitės, kai turinys tikrai apibrėžtas puslapio apimtimi ir puslapio tapatybė yra jo reikšmės dalis
Praktinis apribojimas — palaikymas. Puslapio lygio susietieji failai yra PDF 2.0 konstrukcija, ir peržiūros programų palaikymas plonesnis nei dokumento lygio priedų. Kadangi turinys abiem atvejais sėdi vardų medyje, peržiūros programa, ignoruojanti /AF puslapiuose, vis tiek parodo failą savo priedų sąraše, todėl degradacija maloni. Bet jei puslapio susietis jūsų vartotojui yra esminis, o ne tik naudingi metaduomenys, patikrinkite skaitytuvą, į kurį iš tikrųjų taikotės, o nesitikėkite
Puslapio lygio susietieji failai, dokumento lygio priedai ir archyvinių profilių vartai, valdantys abu, pateikiami kartu su PDFlibPas Delphi PDF biblioteka. Jei pakeliui į vidų dar ir remontuojate senesnius failus, metaduomenų ir suderinamumo darbas, aprašytas straipsnyje konvertavimas į PDF/A su metaduomenų remontu, yra tai, kas iš pradžių nusprendžia, kuris iš šių priedų kelių jums apskritai prieinamas