跳到內容

線性化:Fast Web View 輸出

線性化 PDF,也就是 Fast Web View,會透過特定布局,讓讀取端能在檔案其餘部分尚未抵達前先顯示第一頁。第一頁的物件、其交叉參照子區段,以及用來定位其他每一頁的提示表,都會放在檔案前段。NextPDF 會以確定性方式輸出這套布局:相同文件在每一台主機上都會產生相同的位元組,且結果可通過 qpdf --check-linearization 檢查。

線性化是一項 Core 功能。你可以在 Document 上啟用;引擎會處理三趟布局、線性化參數字典與提示表。讀取端的 LinearizationView 會剖析已完成檔案的線性化字典,讓傳輸層(transport)不必重新實作這套格式,就能規畫傳遞。

Terminal window
composer require nextpdf/core:^3

標準 PDF 會把交叉參照表放在檔案最尾端,因此讀取端必須先取得檔案尾段,才能解析(resolve)任何物件。線性化 PDF 會把檔案重新排列成兩個部分。第一部分包含線性化參數字典、第一頁,以及頁面偏移提示表。第二部分包含其餘各頁。支援 Fast Web View 的讀取端可以先從第一部分繪製第一頁,再利用提示表,在位元組持續抵達時直接定位到後續任何一頁——ISO 32000-2 Annex F。

NextPDF 提供兩種後端(backend)。預設的 v2 後端是三趟線性化器,會產生符合 ISO 32000-2 Annex F 的輸出,包含符合規範的頁面偏移提示表,且其 /L 長度會精確等於檔案的位元組長度。保留舊版 v1 後端,是為了與 v2 之前產生的文件維持位元組相容;它會輸出不符規範的 Annex F 參數,而且只有明確選用時才會啟用。新的開發工作應使用預設後端。

確定性是一項嚴格保證。檔案識別碼會從內容摘要推導而來,而不是取自隨機來源,因此 enableLinearization() 是文件的純函式。正是這一點讓黃金位元組測試(golden byte tests)能夠鎖定輸出,也讓下游能實作內容定址快取或穩定的 ETag

examples/linearization/enable.php
<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Core\Document;
$document = Document::createStandalone();
$document->writeHtml('<h1>Quarterly report</h1>');
$document->enableLinearization();
// Deterministic: the same document always produces the same bytes.
$pdf = $document->output();

預設後端是 v2。若要改用舊版 v1 後端,請先呼叫 useLegacyLinearizer()(兩種順序皆可):

$document->useLegacyLinearizer();
$document->enableLinearization();

你也可以透過 Config 以宣告式方式啟用。這項設定會在建構文件時套用,適合一開始就固定好傳遞格式、且不想針對每份文件逐一呼叫方法的管線:

use NextPDF\Core\Config;
use NextPDF\Core\Document;
$config = (new Config())->withLinearization();
$document = Document::createStandalone($config);
$document->writeHtml('<h1>Quarterly report</h1>');
$pdf = $document->output(); // linearized output

withLinearization() 與其他 Config 選項一樣,預設為關閉。傳入 false 可讓這個選擇更明確。以這種方式建構的文件會走相同的 enableLinearization() 路徑,因此下方的規範守衛同樣適用。

線性化可與標記式(tagged)及封存(archival)設定檔搭配使用,但會與那些使前置提示表或位元組範圍簽章失效的功能互斥。

功能互動關係
PDF/A、PDF/UA 設定檔可搭配使用。v2 會保留物件編號,因此結構與標籤參照仍然有效。
加密(AES-256、AES-GCM、公開金鑰)互斥。 提示串流(hint stream)會以明文輸出,因此引擎會拒絕這個組合。
PAdES 簽章互斥。 重新線性化會改寫位元組偏移,並破壞簽章的 /ByteRange
增量更新在單次建構中互斥。

這道守衛是雙向的,且不受呼叫順序影響:要求對已標記為線性化的文件加密(或簽章)會擲出例外;將已加密(或已簽章)的文件標記為線性化也會擲出例外。兩者都會擲出 InvalidConfigException

use NextPDF\Exception\InvalidConfigException;
$document->setEncryption('user-pw', 'owner-pw'); // (userPassword, ownerPassword)
try {
$document->enableLinearization(); // rejected — encryption is already configured
} catch (InvalidConfigException $e) {
// Linearization and encryption cannot be combined on one document.
}

LinearizationView 會剖析已完成 PDF 前段的線性化參數字典。它是傳輸層規畫傳遞時唯一受支援的綁定點;呼叫端不需要自行重新實作字典剖析。

examples/linearization/inspect.php
<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Writer\Linearization\LinearizationView;
$view = LinearizationView::fromPdf($pdf);
if ($view->isLinearized) {
// Plan, e.g., a first-page byte range from the parsed dictionary fields:
// file length, first-page object number, main cross-reference offset,
// hint-table offset and length, first-page end offset, page count.
$firstPageEnd = $view->firstPageEndOffset;
}
型別種類主要成員穩定性自版本
Document類別enableLinearization(): staticuseLegacyLinearizer(): static穩定3.2.0
Config類別withLinearization(bool $linearize = true): self穩定6.1.0
LinearizationView類別fromPdf(string): selflengthMatches(int): bool、公開的唯讀字典欄位穩定3.2.0

enableLinearization() 會在加密或 PAdES 簽章已設定時擲出 InvalidConfigException。對於不含任何線性化字典的文件,LinearizationView::fromPdf() 會回傳一個 isLinearized 旗標為 false 的檢視。

  • 線性化文件無法同時被加密,也無法使用 PAdES 簽章。每次建構只能擇一。
  • 舊版 v1 後端會輸出不符規範的 Annex F 參數,只是為了與較舊的輸出維持位元組相容而存在。規範守衛是針對 v2 執行的。
  • Fast Web View 是一種傳遞最佳化,而非安全性或驗證功能;它不會改變已繪製的頁面內容。