PDF 1.5 esitteli kaksi tallennusrakennetta, joita aikaisemmalla tiedostomuodolla ei ollut mitään keinoa ilmaista: objektivirta ja ristiviittausvirta. Objektivirta on yksi Flate-pakattu kontti, johon on merkitty /Type /ObjStm, joka sisältää monia pieniä epäsuoria kohteita pakattuna päästä päähän sen sijaan, että ne levitettäisiin tiedoston rungon läpi. Ristiviittausvirta on tiedoston hakutaulukko kirjoitettuna uudelleen pakattuna binäärinä, jossa on vaihtelevan levyiset kentät, korvaten kiinteäleveyksisen ASCII-taulukon, joka sulki jokaisen PDF-tiedoston versioon 1.4 saakka. Ne kulkevat yhdessä. Kun objektit on taitettu virtaan, vanha tekstitaulukko ei voi enää osoittaa niitä, joten binäärin xref:n on tultava sen mukana
Laita tämä klassista asettelua vasten ja sen poistama kustannus on helppo nähdä. PDF 1.4 -tiedostossa jokainen epäsuora objekti on pakkaamattomana oman obj -otsikkonsa takana, ja pyrstössä oleva taulukko käyttää tarkalleen 20 tavua ASCII-koodia per merkintä, pakkaus kielletty. Asiakirja, jossa on 200 000 objektia, kuljettaa karkeasti 4 Mt ristiviittaustietoa ennen kuin yhtään glyyfiä on piirretty, kaikki pakkaamattomat sanakirjarungot pinottuina päälle. PDF 1.5 hyökkää molempiin lukuihin kerralla: sanakirjat taittuvat Flate-säiliöihin ja 4 Mt:n taulukko kutistuu muutamaan sataan kilotavuun binääritietoa. ISO 32000-1 määrittelee kaksi rakennetta kohdissa 7.5.7 ja 7.5.8
Minne säästö oikeasti päätyy
Objektivirrat koskettavat vain muita kuin virta-objekteja, joten ne pakkaavat rakenteen, eivät pikseleitä. Sivun sisältö oli jo Flate-pakattu ennen versiota 1.5, ja kuvadata sisältää omat koodekkinsa, minkä vuoksi runsaasti kuvia sisältävä esite hädin tuskin liikkuu. Tiedostot, jotka romahtavat, ovat raskasrakenteisia: AcroForms-tiedostoja, joissa on tuhansia kenttäsanakirjoja, syviä ääriviivapuita, merkittyjä PDF-rakenne-elementtejä. Nämä esineet ovat pieniä, lukuisia ja lähes identtisiä keskenään, ja tämä toisto on juuri sitä, mitä Flate hyödyntää, kun ne istuvat yhdessä puskurissa sen sijaan, että ne leviäisivät kehon poikki ja otsikot on kiilattu niiden väliin
On helppo aliarvioida kuinka suuri osa vanhasta tiedostosta on yleiskustannuksia. Form-arkisto, joka on imenyt itseensä vuosien muokkauksia, voi käyttää selvästi yli puolet tavuistaan sanakirjan otsikoihin, xref -täytteisiin ja versioihin, joita yksikään lukija ei koskaan katso. Tässä olevat kaksi ominaisuutta vaativat näistä kahta ensimmäistä. Kolmas, kertyneet tarkistukset, antautuu tiivistymään vasta, kun tiedoston ei enää tarvitse muistaa omaa historiaansa
HotPDF:ssä kytket molemmat päälle kahden ominaisuuden kautta, ja se kuinka ne riippuvat toisistaan, on tärkeämpää kuin niiden kirjoitusjärjestys:
var
Pdf: THotPDF;
begin
Pdf := THotPDF.Create(nil);
try
Pdf.FileName := 'catalog-2026.pdf';
Pdf.UseXRefStream := True; // binääri xref, edellytys ObjStm:lle
Pdf.UseObjectStreams := True; // pakkaa kohteet kansioon /Type /ObjStm
Pdf.BeginDoc;
Pdf.CurrentPage.SetFont('Arial', [], 11);
Pdf.CurrentPage.TextOut(50, 760, 0, 'Compressed structure demo');
Pdf.EndDoc; // lähettää XRefStm + ObjStm säiliöt
finally
Pdf.Free;
end;
end;
UseObjectStreams edellyttää, että UseXRefStream on True. Pakattuun kohteeseen päästään tyypin 2 xref-merkinnän kautta, joka tallentaa objektivirran numeron sekä indeksin, ja klassisella 20-tavuisella tekstirivillä ei ole paikkaa tallentaa tätä paria. Joten UseObjectStreams ei tee itsenäisesti mitään näkyvää; molemmat liput, asennettu ennen BeginDoc:ia, ovat konfiguraatio joka toimii. Aseta ne komennon BeginDoc jälkeen, ja HotPDF on jo sitoutunut vanhempaan asetteluun
Miksi molempien oletuksena on pois päältä
HotPDF jättää molemmat ominaisuudet alkujaan muotoon False, ja syy ilmenee integraatioissa vanhan jatkovirtakoodin kanssa. Lukija, joka ymmärtää vain PDF 1.4:n, ei ilmoita, ettei se pysty käsittelemään pakattuja kohteita. Se kohtaa xref-virran, ei löydä yhtään odottamiaan traileriavainsanoja ja ilmoittaa vahingoittuneesta ristiviittaustaulukosta tai yksinkertaisesti kieltäytyy avaamasta tiedostoa. Jos tulostesi virtaa ikääntyvään yhdyskäytävään, laitteistotulostimeen, joka käyttää upotettua tulkkia, tai jäsentäjään, jonka joku kirjoitti 1.4-määrityksiä vastaan vuosikymmen sitten, pidä molemmat liput poissa tästä kanavasta ja elä suuremman tiedoston kanssa. Arkistotallennuksessa ja verkkojakelussa, joissa jokainen valtavirran katseluohjelma on lukenut PDF 1.5:tä kaksikymmentä vuotta, niiden kytkeminen päälle on pakkaus, jonka saat melkein ilmaiseksi
On olemassa toisen asteen vaikutus, josta kannattaa kertoa tukitiimillesi. Kun sanakirjat on pakattu objektivirtoihin, kahden luodun tiedoston vertailu tavu kerrallaan lakkaa merkitsemästä mitään, koska yksittäisen kentän muuttaminen voi uudelleen litistää kokonaisen kontin ja sekoittaa kaiken sen jälkeen olevan. Vertaile tällaisia tiedostoja objektisisällön, ei binäärivertailun perusteella
Inkrementaaliset päivitykset ja niiden suojaamat tavusiirtymät
Digitaalinen allekirjoitus kattaa nimenomaisen alueen /ByteRange: fyysisen tiedoston kahden jännevälin, jotka on annettu absoluuttisina tavupoikkeamina ja joiden yli CMS-tiivistelmä otettiin. Kirjoita tiedosto uudelleen, jopa sellaiseksi, joka näyttää näytöllä samalta, ja nuo siirtymät kaikki siirtyvät. Tiivistelmä lakkaa vastaamasta ja allekirjoitus lukee rikkinäisenä. Tämä on tarkalleen ongelma, jonka ISO 32000-1 §7.5.6 ratkaisee inkrementaalisilla päivityksillä. Uudet ja muuttuneet objektit liitetään olemassa olevan komennon %%EOF jälkeen, jolloin kirjoitetaan uusi ristiviittausosa, jonka /Prev -merkintä osoittaa takaisin edelliseen. Alkuperäisiä tavuja ei koskaan häiritä, joten allekirjoitettu versio pysyy todennettavana, ja Acrobat voi esittää jokaisen allekirjoitetun version erikseen allekirjoituspaneelissa
HotPDF paljastaa tämän oman sisääntulopisteensä kautta:
Pdf.BeginIncrementalUpdate('contract-signed.pdf');
Pdf.AddPage;
Pdf.CurrentPage.SetFont('Arial', [], 10);
Pdf.CurrentPage.TextOut(50, 760, 0, 'Addendum recorded 2026-06-11');
Pdf.SaveIncrementalUpdate('contract-updated.pdf'); // liittää vain delta
Kaksi asiaa saavat ihmiset kompastumaan. BeginIncrementalUpdate -tietokoneen on vastaanotettava alkuperäinen tiedostonimi, koska liitetyssä xref-osiossa tallennetaan siirtymiä, jotka ovat mielekkäitä vain alkuperäisiä tavuja vastaan. osoita se uudelleen nimettyyn tai uudelleen tallennettuun kopioon, jolloin siirtymät kuvaavat tiedostoa, jota ei enää ole olemassa. Ja tallennus on rakenteeltaan vain lisättävä, joten tuloste on aina suurempi kuin syöttö. Tämä kasvu ei ole hukkaan menevää pois viritettävää. Sillä on sama ominaisuus, joka jättää aiemmat allekirjoitetut versiot ennalleen
Ladatun tiedoston muokkaaminen tapahtuu toiminnon LoadFromFile kautta
Kehittäjät, jotka tapasivat HotPDF:n ensimmäisen kerran sen sukupolven sovellusliittymän kautta, törmäävät usein tiettyyn seinään. BeginDoc avaa aivan uuden asiakirjan, joka on väärä työkalu, kun haluat muuttaa jo olemassa olevaa dokumenttia. Olemassa olevan tiedoston muokkaaminen suoritetaan sen sijaan ladatun asiakirjan kutsujen kautta:
PageCount := Pdf.LoadFromFile('base.pdf');
Pdf.InsertPagesFromDocument(OtherDoc, '1-3', 5); // sivut 1-3 sivun 5 jälkeen
Pdf.MovePage(2, 5);
Pdf.SaveLoadedDocument('modified.pdf');
Sekoita nämä kaksi toisiinsa ja oireena on tulostiedosto, joka sisältää uuden sisällön eikä mitään alkuperäisestä, koska BeginDoc rakensi iloisesti tuoreen asiakirjan sen viereen, jota luulit editoivasi. Lue komento LoadFromFile komennolla SaveLoadedDocument yhdeksi sanastoksi ja BeginDoc komennolla EndDoc toiseksi. Rutiini, joka kurkottaa molempia samaa tiedostoa vastaan, on melkein aina väärä
Milloin liitetty tiedosto pakataan
Vain lisäyksiä sisältävään tallennukseen liittyy hidas kustannus. Yöllinen työ, joka lyö yhden tilarivin samaan PDF-tiedostoon, tuottaa 365 versiota vuoden aikana, ja jokainen tarkistus hinaa takanaan uuden xref-osion. Kun tuo historia on ylittänyt käyttökelpoisuutensa, eikä yhdenkään tiedostossa olevan allekirjoituksen tarvitse selviytyä, voit tasoittaa koko asian sarjoittamalla sen uudelleen ladatun asiakirjan polun kautta:
Pdf.LoadFromFile('stamped.pdf');
Pdf.SaveLoadedDocument('compacted.pdf');
Tämä uudelleentallennus on täydellinen uudelleenkirjoitus. Se heittää aiemmat versiot pois tarkoituksella ja rikkoo minkä tahansa tiedostossa vielä olevan allekirjoituksen, joten aseta se saman käytäntöportin taakse, jota sovelletaan mihin tahansa muuhun tuhoavaan vaiheeseen. Yksi tuotantosääntö, joka kestää: pakkaa, kun versioiden määrä ohittaa kynnyksen tai kun liitetyt yleiskulut kasvavat jonkin perussivun yli ja älä koskaan tiivistä asiakirjaa, jonka allekirjoituspaneelissa on jotain
Tulosteen tarkistaminen ennen lähettämistä
Tämän ominaisuusparin tarkistaminen on virkistävän konkreettista. Avaa tulos Adobe Acrobatissa ja vahvista kolme kohtaa: asiakirjan ominaisuudet raportoivat PDF 1.5:stä tai uudemmasta, kun objektivirrat ovat päällä; allekirjoituspaneeli vahvistaa edelleen jokaisen aiemmin allekirjoitetun version lisäyspäivityksen jälkeen; ja sivumäärä sekä kirjanmerkit selvisivät lataus-, muokkaus- ja tallennusjaksosta vahingoittumattomana. Pakota tiedosto arkistotulostusta varten myös veraPDF:n läpi, koska pakattu xref on juuri sellainen rakenne, jota tiukka validaattori tutkii tarkemmin kuin anteeksiantava katselija koskaan tekee. Jos työhösi liittyy myös erittäin suuria panoksia, kohdassa suorien tiedostojen sovellusliittymän suuria PDF-työnkulkuja varten katsauksemme käsitellyt tarkistusmenetelmät sopivat luonnollisesti osittaiseen tallentamiseen ja yllä olevien tavualueiden takana olevaa allekirjoitusmekaniikkaa käsitellään perusteellisesti artikkelissa HotPDF-digitaaliset allekirjoitukset ja PAdES
Molemmat ominaisuudet toimitetaan osana HotPDF Component -ominaisuuksia Delphille ja C++Builderille luomis-, lomake-, salaus- ja allekirjoitussovellusliittymien vieressä, joita käsitellään muualla tässä blogissa. Tuotesivu linkittää täydellisen API-viitteen, jos haluat asettaa yllä olevat puhelut omaa dokumenttiasi vastaan