跳到內容
getnextpdf.com

Fast Web View:PDF 如何在下載完成之前就開啟

Spec: ISO 32000-2, Annex F

一份線性化的 PDF 經過重新編排,讓第一頁與一份小巧的導覽索引坐落在檔案的最前端。因此,檢視器可以在文件其餘部分仍在抵達時就先繪製第一頁,也能直接跳到第 147 頁,而不必先讀過第 2 到 146 頁。

這正是多數讀者以其親切名稱熟知的功能:Fast Web View

想像一份 200 頁的報告,在一支只剩一格訊號的手機上開啟。若沒有線性化,檢視器往往需要拿到檔案的最末端才能繪製任何內容,因為那份標明每個物件位置的主索引,傳統上是坐落在檔案後段。於是你只能盯著轉圈圈的圖示,看著兩百頁全部下載完,就為了讀第一頁。

有了線性化,檔案的編排方式讓「第一頁上有什麼」的答案成為最先離開傳輸線的東西。讀者在一秒內就把第一頁繪製出來,其餘部分只在你捲動或跳頁時才取得。在快速連線上,你或許永遠不會察覺。但在緩慢或計量收費的連線上,這就是一份可用文件與一個被放棄的分頁之間的差別。

  • 線性化的檔案是前置載入的:第一頁與一份提示表被放在最前面,先於本體的其餘部分。
  • 提示表是一張範圍地圖。它告訴檢視器哪些位元組範圍屬於每一頁、哪些屬於共用物件,讓檢視器可以向伺服器索取恰好那幾段切片——接著由交叉參照表把每個物件編號解析到它確切的偏移量。
  • 這仰賴位元組範圍請求——檢視器依需求擷取檔案的切片,而非整個檔案。
  • 這些位元組與一份正常 PDF 的內容完全相同。線性化改變的是順序與索引,而非頁面本身。
  • 在 NextPDF 中,這是一個明確、可切換的步驟——由一套真正的三趟重建產生,而不是一個只能祈求順利的旗標。

你無法在尚未確切知道每樣東西有多大之前就把某一頁前置載入,因為提示表記錄的是位元組偏移量,而偏移量唯有在每個物件的長度都已定案後才會正確。這種循環性——偏移量取決於大小,大小取決於版面——正是線性化器要分趟執行、而非一次掃過的原因。

NextPDF 以一套確定性的三趟重建來化解它。第一趟測量,第二趟決定放置位置,第三趟以此時已知的偏移量把真正的位元組寫出來。

  1. MEASURESerialise every object once to learn its exact byte length. Offsets are circular — they depend on sizes — so sizes are pinned first.
  2. PLACEDecide the order: first page and its dependencies up front, then the rest. Reserve space for the linearization parameter dictionary and the hint table.
  3. FILLWrite the final bytes. Each reserved field is filled with values computed after MEASURE and PLACE — the first-page length, the hint-table location, the main cross-reference offset — derived from the measured sizes and the chosen placement.
The three-pass linearization rebuild. MEASURE sizes every object so lengths are final; PLACE decides the front-loaded order and reserves the hint-table region; FILL writes the real bytes with the now-known offsets, so the first page and the hint table land at the front and the cross-reference data resolves on first fetch.

輸出以一份線性化參數字典作為其第一個物件,並帶有一份或多份用來索引各頁的提示表,完全依照標準所規定(Spec: ISO 32000-2, Annex F)。這些提示表與一份傳統的交叉參照表並肩運作——提示表記錄檢視器擷取所需的位元組範圍與位置,而交叉參照表則是把每個物件編號對應到其確切位元組偏移量的索引。NextPDF 的線性化器輸出經典的表格形式,並在過程中清除任何交叉參照串流,因此一旦某段切片抵達,讀者便能直接從那張表以其偏移量解析出一個物件(Spec: ISO 32000-2, §7.5.4)。

一個有用的心智模型:一份正常的 PDF 是一本目錄被黏在封底的書。線性化的 PDF 把那一頁目錄移到最前面,並加上一份逐頁的頁碼索引,讓你可以直接翻到任何一頁。各章節並未改變。移動的只有導覽部分。

線性化是一個明確、可切換的步驟。你提出要求;引擎執行重建,並輸出一份 Fast-Web-View 檔案。

<?php
declare(strict_types=1);
use NextPDF\Core\Document;
use NextPDF\Contracts\OutputDestination;
$document = Document::createStandalone();
$document->setTitle('Annual Report');
for ($page = 1; $page <= 200; $page++) {
$document->addPage();
$document->setFont('helvetica', '', 12);
$document->cell(0, 12, "Page {$page}", newLine: true);
}
// Linearization is requested explicitly — an operability choice, not a default.
// enableLinearization() takes no arguments; it is the on-switch. The engine
// runs the MEASURE -> PLACE -> FILL rebuild and emits a Fast-Web-View file
// with the first page and hint table at the front.
$document->enableLinearization();
$bytes = $document->output(dest: OutputDestination::String);

頁面內容正是你所撰寫的內容。差別在於你所收到位元組的檔案順序,以及那份此時坐落在接近頂端位置的提示表。

你會以一個陌生人會採用的方式驗證結果——藉助外部檢查工具:

$ qpdf --check-linearization report.pdf
report.pdf: no linearization errors

qpdf --check-linearization 不只是尋找一個旗標。它會重新推導出檔案所宣稱的偏移量,並確認它們屬實:第一頁的物件確實位於線性化字典所指出的位置、提示表指向正確的位元組,且結構符合 Annex F。一份對自己版面說謊的檔案,即使乍看之下像是線性化的,仍會無法通過這項檢查。

常見的假設是,線性化會壓縮檔案,或讓下載整體變快。它兩者都不會。一份線性化的檔案往往更大幾個位元組,因為它額外帶有提示表。整份文件的總傳輸時間基本上不變。

改變的是第一個有用的像素何時出現。線性化最佳化的是到第一頁的時間,而非總位元組數。它是一項延遲功能,而非壓縮功能。盡早串流出第一頁,與快速下載完整個檔案,是不同的目標,而線性化服務的是前者。

第二個誤解是,任何網頁伺服器都會串流一份線性化的檔案。檢視器需要擷取位元組範圍,這意味著伺服器必須兌現 HTTP 範圍請求。多數伺服器都能,但一個總是回傳整個檔案的伺服器,會把 Fast Web View 變回緩慢的整檔等待——檔案已準備好串流,但傳輸層卻沒有。

NextPDF 對產生線性化檔案具備完整的核心支援:一套正式產品級的三趟線性化器,會輸出參數字典與提示表,並能通過外部的 Annex F 檢查。

Fast Web View (linearization) output — edition availability
EditionAvailability
Core

Full support. NextPDF produces linearized (Fast Web View) output through a production three-pass MEASURE → PLACE → FILL rebuild, conforming to ISO 32000-2 Annex F.

ProNot in this edition
EnterpriseNot in this edition

有兩條邊界值得點明。第一,線性化是單一修訂版本的屬性。在你附加一次增量更新的那一刻——一個簽章、一次表單填寫、一處編輯——附加的位元組會放到結尾,於是檔案便不再嚴格屬於線性化,直到它被重建為止。這是一種正常的取捨,而非缺陷;關於為何附加才是已簽署文件的正確行為,參見增量更新

第二,引擎掌控檔案,卻不掌控網路。Fast Web View 唯有在提供服務的連線兌現位元組範圍請求時,才能兌現它的承諾;即使位元組完美地經過線性化,只要伺服器堅持送出整個檔案,它們仍會以一個緩慢的整塊形式抵達。

  • PDF 檔案剖析 — 線性化所重新編排的標頭、本體、交叉參照表與尾段。先讀這篇,看看被重新排序的究竟是什麼。
  • 記憶體與串流 — 寫入端的串流,一條不同的軸線:NextPDF 在產生位元組時如何讓記憶體維持平穩,相對於讀者如何把它們串流進來。
  • 增量更新為何重要 — 為何後續的編輯會附加到結尾,以及這對一份線性化檔案的前置載入版面意味著什麼。
  • 串流與篩選器 — 提示表所指向的本體物件裡頭住著什麼,以及它們如何被壓縮。
  • 線性化 — 把第一頁與一份導覽索引前置載入的那套重建,讓檢視器能在整個檔案抵達之前就進行繪製與導覽。這是標準對其結果所取的名稱。
  • Fast Web View — 線性化 PDF 面向消費者的名稱;這兩個詞描述的是同一份檔案。
  • 提示表 — 線性化檔案內部記錄每一頁與共用物件之位元組範圍與位置的結構,讓檢視器知道該請求哪些切片;交叉參照表則是接著把物件編號對應到其確切位元組偏移量的東西。
  • 線性化參數字典 — 線性化檔案中的第一個物件;它宣告那些讓依需求擷取得以成立的關鍵偏移量(第一頁長度、提示表位置、主交叉參照位置)。
  • 位元組範圍請求 — 一個只索取檔案某段切片、而非整個檔案的 HTTP 請求;這是 Fast Web View 所仰賴的傳輸機制。
  • 到第一頁的時間 — 讀者看到第一頁所需的時間。線性化所最佳化的延遲,有別於總下載時間。