Перейти к содержимому
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.
Трёхпроходная пересборка линеаризации. MEASURE определяет размер каждого объекта, чтобы длины стали окончательными; PLACE решает порядок размещения «вперёд» и резервирует область таблицы подсказок; FILL записывает реальные байты с уже известными смещениями, так что первая страница и таблица подсказок оказываются в начале, а данные перекрёстных ссылок разрешаются при первом запросе.

В выводе первым объектом идёт словарь параметров линеаризации, а также одна или несколько таблиц подсказок, индексирующих страницы, — ровно так, как предписывает стандарт (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

Полная поддержка. NextPDF производит линеаризованный вывод (Fast Web View) через промышленную трёхпроходную пересборку MEASURE → PLACE → FILL, соответствующую 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.
  • Время до первой страницы — сколько проходит до того, как читатель увидит первую страницу. Задержка, которую оптимизирует линеаризация, отличная от общего времени загрузки.