Legg en 80 MB skannet rapport bak en lenke, åpne den i en nettleser, og se hva som skjer: visningsprogrammet sitter på en blank rute til en stor andel av disse bytene har ankommet, deretter maler den side én alt på en gang. Hopp til side 40, og på en dårlig bygget fil kan hele nedlastingen starte på nytt. Det frustrerende er at leseren egentlig bare ville ha den første siden. Linearisering er det strukturelle svaret på det problemet. Det omarrangerer en PDF slik at et visningsprogram kan gjengi åpningssiden fra et lite prefiks av filen og hente resten ved behov, noe som er grunnen til at Adobe markedsfører funksjonen som "Fast Web View."
Ingenting av dette er et annerledes filformat. En linearisert PDF er en vanlig PDF som en kompatibel leser vil åpne uten spesiell håndtering. Trikset ligger utelukkende i hvordan bytene er ordnet og i to ekstra strukturer filen bærer. ISO 32000-1 spesifiserer hele ordningen i Vedlegg F, og når du først har sett oppsettet, slutter atferden å se ut som magi og begynner å se ut som et bevisst bytte av filrekkefølge for førstegangstegning-latens
Hva linearisering faktisk omarrangerer
En normal PDF kan spre objektene sine i nesten hvilken som helst rekkefølge. Kryssreferansetabellen på slutten av filen er det som får det til å fungere: en leser søker til slutten, leser startxref-pekeren, laster inn xref, og derfra kan den finne hvert objekt etter dets forskyvning. Dette designet er utmerket for lokale filer, der det koster ingenting å søke til slutten, og dårlig for en fil som strømmes inn over et nettverk, der slutten er nøyaktig den delen som ankommer sist. For å gjengi side én trenger en konvensjonell leser sideobjektet, dets innholdsstrøm, skrifttypene det refererer til, og eventuelle bilder det tegner, og i en uordnet fil kan disse sitte hvor som helst, inkludert i den siste megabyten
Linearisering fikser rekkefølgen. Objektene som trengs for å vise den første siden samles i en sammenhengende blokk nær fronten, rett etter en liten hodeseksjon, slik at de ankommer tidlig i bytestrømmen. Alt annet, de gjenværende sidene og ressursene de deler, følger i en forutsigbar sekvens. En andre, komplett kryssreferansetabell lever fortsatt på slutten for lesere som ignorerer optimaliseringen, men en linearisert fil plasserer også en kryssreferanse for første side og parametrene en strømmende leser trenger helt foran. Leseren trenger ikke lenger å nå halen før den kan tegne noe
Førsteside-objektsettet og ordboken for lineariseringsparametere
Det aller første objektet i en linearisert fil, etter %PDF-hodet, er ordboken for lineariseringsparametere. Det er det en strømmende leser ser etter for å avgjøre om optimaliseringen er til stede og hvordan den skal brukes. Ordboken registrerer lengden på hele filen, byteforskyvningen der den viktigste kryssreferanseseksjonen begynner, objektnummeret til den første siden, og plasseringen og lengden på hintstrømmen som følger. Med disse tallene vet en leser, bare fra de første kilobytene, hvor mye den må hente for å vise side én, og hvor den skal lete etter indeksen som lar den hoppe et annet sted
Vedlegg F er strengt på hva "første side" betyr her. Førstesideseksjonen må inneholde selve sideobjektet, dets innholdsstrømmer, og ressursene disse strømmene refererer til, slik at siden er selvtilstrekkelig når det prefikset er lastet ned. Delte ressurser, en skrifttype brukt på hver side, en logo som gjentas i et topptekst, håndteres spesielt: de dukker opp tidlig nok til å betjene den første siden, men flagges som delte slik at leseren ikke henter dem på nytt når den senere gjengir side 30. Det skillet mellom sideprivate og delte objekter er det de fleste hjemmesnekrede "optimalisatorer" gjør feil, og å gjøre det feil er det som produserer en fil som hevder å være linearisert, men som likevel stopper opp
Hintstrømmer: indeksen som gjør sidehopp billige
Å vise side én raskt er bare halve verdien. Den andre halvdelen er å hoppe til en vilkårlig side uten å laste ned alt i mellom, og det er hva hintstrømmene gir. En linearisert fil bærer en hint-tabell for sideforskyvninger og en hint-tabell for delte objekter, lagret som en strøm det refereres til fra parameterordboken. Sideforskyvningstabellen registrerer, for hver side, hvor objektene dens begynner i filen og hvor lange de er. Den delte objekttabellen gjør det samme for ressurser som brukes på tvers av flere sider
Gitt disse tabellene, vil ikke en leser som vil ha side 40, tolke filen sekvensielt. Den konsulterer hint-tabellen for å lære hvilket byteområde side 40 opptar, ber serveren om nøyaktig det området, og gjengir siden når disse bytene ankommer, og trekker inn eventuelle delte ressurser den ikke allerede har, gjennom samme mekanisme. Hintstrømmen er, i praksis, et kart for vilkårlig tilgang lagt over dokumentet, og det er grunnen til at en godt linearisert fil på 500 sider føles responsiv over en treg forbindelse, mens en uoptimalisert en av samme størrelse ikke gjør det
Hvorfor serveren må samarbeide
Linearisering forutsetter at transporten kan levere vilkårlige skiver av filen, og den antakelsen er verdt å sjekke før du gir formatet skylden for dårlige resultater. Mekanismen er HTTP byte-servering: leseren utsteder områdeforespørsler (range requests), og serveren svarer på dem med 206 Partial Content-svar. Hvis serveren ikke annonserer Accept-Ranges: bytes, eller hvis en proxy eller CDN foran den slår sammen områdeforespørsler til fulle overføringer, har leseren ingen måte å hente side 40 isolert, og faller tilbake til å laste ned hele filen. Strukturen inne i PDF-en er da perfekt riktig og fullstendig bortkastet
Dette er feilen som oftest feildiagnostiseres som at "linearisering ikke fungerer." Filen er grei; leveringsveien er det ikke. Før du bygger om et dokument, bekreft med en betinget forespørsel at verten faktisk returnerer delvis innhold for URL-en leseren treffer. Mange statiske verter gjør dette som standard, og mange feilkonfigurerte applikasjonsservere og hurtigbufferlag gjør det ikke
Inkrementelle oppdateringer ødelegger i det stille linearisering
Her er begrensningen som overrasker folk som genererer lineariserte filer riktig og deretter lurer på hvorfor optimaliseringen fordamper. Linearisering er avhengig av ett enkelt, nøye ordnet oppsett med indeksen foran. En inkrementell oppdatering bryter dette ved design. Når et verktøy legger til en signatur, fyller ut et skjemafelt eller legger til en annotasjon gjennom en inkrementell lagring, skriver det ikke om filen. Den legger til de endrede objektene, en ny kryssreferanseseksjon og en ny trailer på slutten, og lar de originale bytene være urørt. Det tillegget er hele poenget med inkrementelle oppdateringer: det er raskt, og det bevarer den tidligere revisjonen for revisjon eller signaturvalidering
Bivirkningen er at filen nå har sine nyeste kryssreferansedata i halen, etter den nøye plasserte førsteside-blokken, og ordboken for lineariseringsparametere foran beskriver et oppsett som ikke lenger samsvarer med filen. En kompatibel leser oppdager avviket og behandler dokumentet som en normal, ikke-linearisert PDF. Fast Web View er borte, selv om den opprinnelige lineariserte strukturen fortsatt sitter der i første halvdel av filen. Hvis du legger til flere oppdateringer, stabler hver av dem nok en revisjon på slutten, og gapet mellom den utdaterte frontindeksen og den virkelige tilstanden utvides
Hvis arbeidsflyten din krever både redigeringer og Fast Web View, følger regelen direkte av strukturen: rediger inkrementelt mens dokumentet er i bevegelse, og re-lineariser deretter én gang på slutten. En full omskriving er det som gjenoppretter oppsettet. I HotPDF-termer betyr det at en pågående redigering går gjennom BeginIncrementalUpdate og SaveIncrementalUpdate, som legger til et delta, mens det avsluttende trinnet laster inn hele dokumentet og serialiserer det på nytt med LoadFromFile etterfulgt av SaveLoadedDocument, som fjerner de akkumulerte gamle revisjonene og avgir ett rent oppsett. Den samme avveiningen dukker opp med objektstrømmer: å aktivere UseObjectStreams sammen med UseXRefStream komprimerer kryssreferansen og pakker objekter tett, noe som hjelper filstørrelsen, men, som ethvert strukturelt valg, må dette brukes under den siste omskrivingen fremfor å boltes fast på en tilføyd revisjon
var
Pdf: THotPDF;
begin
Pdf := THotPDF.Create(nil);
try
Pdf.LoadFromFile('draft_with_updates.pdf');
// These choices require a full rewrite to take effect
Pdf.UseObjectStreams := True;
Pdf.UseXRefStream := True;
// SaveLoadedDocument flattens the updates and writes a clean structure
Pdf.SaveLoadedDocument('final_clean.pdf');
finally
Pdf.Free;
end;
end;
HotPDF eksponerer ikke en "lineariserings"-rutine i ett kall, så det praktiske mønsteret er å produsere en ren, fullstendig omskrevet fil og kjøre en dedikert optimalisator over den. Kommandolinjeverktøy håndterer omorganiseringen direkte. qpdf skriver om en fil til linearisert form med et enkelt flagg:
qpdf --linearize final_clean.pdf ready_for_web.pdf
Hvordan du kan se om en fil er linearisert
Stol ikke på filnavnet eller verktøyet som hevder å ha produsert den; verifiser bytene. Den mest direkte sjekken er hodet til filen: åpne den og se etter ordboken for lineariseringsparametere som det første objektet etter hodet, som bærer /Linearized-nøkkelen. En leservendt snarvei er Acrobats dialogboks for dokumentegenskaper, som rapporterer "Fast Web View: Ja" bare når strukturen er genuint til stede og aktuell
For skriptede sjekker rapporterer qpdf både tilstedeværelsen og integriteten til strukturen, noe som er viktig fordi en fil kan bære en lineariseringsordbok som ikke lenger gjenspeiler dens layout, nøyaktig den tilstanden en inkrementell oppdatering etterlater seg:
$ qpdf --check ready_for_web.pdf
checking ready_for_web.pdf
PDF Version: 1.7
File is linearized
Valideringstrinnet er det som tjener til livets opphold. En gjennomgang som bare bekrefter at ordboken eksisterer, vil gladelig velsigne en fil hvis indeks peker på feil forskyvninger; en sjekk som avstemmer hint-tabellene mot de faktiske objektposisjonene er det som forteller deg at optimaliseringen vil holde stand under en ekte lesers områdeforespørsler
Linearisering er fremdeles verdt å bruke på ethvert stort dokument som serveres over nettet, spesielt for mobillesere på ujevne tilkoblinger, og det koster et par prosent av filstørrelsen for den forhåndslastede indeksen. De to tingene å holde styr på, er at strukturen inne i PDF-en og byte-serveringen utenfor begge må være riktige, og at enhver redigering i etterkant opphever optimaliseringen til du skriver filen på nytt. Behandle re-linearisering som det siste trinnet i rørledningen, etter at hver annen endring er på plass. Kryssreferanse-, objektstrøm- og inkrementell-oppdatering-oppførselen beskrevet her er en del av den strukturelle modellen HotPDF Component for Delphi og C++Builder implementerer; for den bredere bakgrunnen for fillayout se hvordan en PDF er strukturert, og for arbeidsflyten med inkrementelle oppdateringer og store filer i kode se prosessering av store PDF-er fra Delphi