Категория

Линеаризация PDF для быстрого веб-просмотра в JavaScript (React)

2026-10-10 09:05:42 Allen Yang
AI Summarize:
ChatGPT
ChatGPT ✓
Claude ✓
Grok ✓
Perplexity ✓
Quick
Quick
Concise overview
Highlights
Key takeaways
Detailed
Structured explanation
Brief
One sentence summary
Summarize |

Перестройка внутренней структуры PDF для быстрого веб-просмотра в браузере с помощью Spire.PDF for JavaScript

Вы нажимаете ссылку на большой PDF-файл и видите пустой фрейм. Крутится индикатор загрузки, приходят несколько мегабайт, и только потом появляется первая страница. С файлом всё было в порядке, сеть тоже была в порядке — документ просто был записан в таком порядке, который заставляет средство просмотра ждать загрузки всего файла, прежде чем что-либо отрисовать. Именно эту проблему решает линеаризация, и это структурное исправление, а не исправление размера: те же самые байты, упорядоченные так, что части, необходимые для отображения первой страницы, находятся в начале.

В этой статье выполняется линеаризация PDF в браузере с помощью Spire.PDF for JavaScript. Библиотека работает на WebAssembly и обрабатывает документ через виртуальную файловую систему (VFS), поэтому файл можно перестроить на машине пользователя, не отправляя его через удалённый сервис оптимизации.

Инструкции по установке приведены в разделе Интеграция Spire.PDF for JavaScript в проект React. В приведённом ниже примере предполагается, что пакет установлен и модуль WebAssembly инициализирован.


Что на самом деле означает быстрый веб-просмотр

PDF — это контейнер, и его объекты хранятся в том порядке, в котором они были записаны тем, что его создало. Средству просмотра, напротив, нужен определённый небольшой набор — каталог документа, дерево страниц и объекты, лежащие в основе первой страницы, — прежде чем оно сможет что-либо отрисовать. Если эти объекты оказались ближе к концу файла, за большим встроенным изображением, у средства просмотра нет выбора, кроме как продолжать загрузку, пока оно до них не доберётся.

Быстрый веб-просмотр — это название, обращённое к потребителю, для линеаризованного PDF: такого, внутренняя структура которого размещает объекты первой страницы ближе к началу, так что клиент, поддерживающий HTTP-запросы диапазона байтов, может запросить только эти байты, немедленно отобразить первую страницу и загрузить остальное в фоновом режиме. Читатель видит содержимое, пока загрузка продолжается, вместо того чтобы смотреть на пустой фрейм.

Практическое следствие состоит в том, что два файла одинакового размера могут ощущаться при открытии совершенно по-разному. То же количество страниц, те же изображения, тот же текст — разное время до первой отрисовки.


Как линеаризация перестраивает файл

Линеаризация переписывает структуру файла, не затрагивая его содержимое:

  • Объекты, от которых зависит первая страница, перемещаются в начало файла.
  • Словарь линеаризации записывается ближе к началу, чтобы клиент мог обнаружить структуру до того, как прочитает весь документ.
  • Таблица подсказок фиксирует, где расположены объекты каждой страницы, что позволяет программе чтения перейти вперёд к произвольной странице с помощью запроса диапазона байтов.
  • Информация о перекрёстных ссылках размещается так, чтобы её можно было прочитать раньше, а не в конце файла.

Всё, что читатель действительно видит — текст, изображения, шрифты, векторную графику, ссылки, аннотации, закладки, метаданные, — переносится без изменений. Слова на странице — те же слова в тех же местах. Изменился порядок байтов, а не содержимое. Вот почему линеаризованный документ невозможно распознать, просто взглянув на него: откройте оригинал и результат рядом, и они неотличимы, потому что разница проявляется только в том, когда части могут быть прочитаны.


Линеаризация документа в браузере

Использование повторяет другие конвертеры библиотеки: передайте входной файл в PdfToLinearizedPdfConverter, затем вызовите ToLinearizedPdf, чтобы записать перестроенный документ.

function App() {
  const convertToLinearized = async () => {
    // Get the Spire.PDF WASM module
    const pdfModule = window.wasmModule?.spirepdf;

    // Check whether the module is ready
    if (!pdfModule) {
      alert('Spire.PDF is not ready yet');
      return;
    }

    // Load the PDF file to be converted into the VFS
    const inputFileName = 'Business_Data_Overview.pdf';
    await window.spire.FetchFileToVFS(inputFileName, "", `${process.env.PUBLIC_URL}/data/`);

    // Define the output file name
    const outputFileName = 'LinearizedDocument.pdf';

    // Construct the linearization converter from the input file and write out the linearized document
    const converter = new pdfModule.PdfToLinearizedPdfConverter({ filePath: inputFileName });
    converter.ToLinearizedPdf({ filePath: outputFileName });
    converter.Dispose();

    // Read the generated file from the VFS and trigger the download
    const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
    const blob = new Blob([fileArray], { type: 'application/pdf' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = outputFileName;
    a.click();
    URL.revokeObjectURL(url);
  };

  return (
    <div style={{ textAlign: 'center', height: '300px' }}>
      <h1>Linearize a PDF</h1>
      <button onClick={convertToLinearized}>
        Start Converting
      </button>
    </div>
  );
}

export default App;

ToLinearizedPdf записывает новый файл, поэтому входной файл остаётся в VFS и оригинал доступен для сравнения. Вызов никак не зависит от содержимого документа — отчёт, руководство и отсканированный архив проходят через одни и те же два члена.

Линеаризованный документ выглядит на странице точно так же, изменение находится внутри структуры файла

Линеаризованный документ выглядит на странице точно так же, изменение находится внутри структуры файла


Линеаризовать или сжимать

Эти два прохода регулярно путают, потому что оба описываются как «оптимизация PDF», но они отвечают на разные вопросы.

Сжатие Линеаризация
Что изменяет Удаляет избыточность, поэтому файл содержит меньше байтов Переупорядочивает байты так, чтобы полезные приходили первыми
Цель Меньший объём загрузки Более быстрая первая страница
Влияние на размер файла В этом и смысл упражнения Практически никакого; байты остаются теми же байтами
Влияние на внешний вид Только если в жертву принесено качество изображения Совсем никакого
Типичный повод Ограничение на загрузку или лимит вложения Длинный документ, опубликованный для просмотра

Файлу может потребоваться и то, и другое, и порядок имеет значение. Сжатие переписывает документ, а любой проход, переписывающий PDF, уничтожает линеаризованную структуру — поэтому, если вам нужно и то, и другое, сначала сжимайте, а линеаризуйте в конце, чтобы линеаризованная структура была конечным состоянием файла.


Когда линеаризация того стоит

Линеаризация окупается в определённой ситуации: документ достаточно большой, чтобы загрузка была заметной, доставляется по HTTP средству просмотра, поддерживающему запросы диапазонов.

  • Руководства, каталоги и длинные отчёты, размещённые на сайте. Это классический случай — десятки мегабайт, открываются по ссылке, а читатели хотят сразу перейти к нужной главе.
  • Мобильные читатели на медленных соединениях. Первая страница появляется из первых запрошенных байтов, поэтому воспринимаемое время загрузки снижается, даже если общая загрузка — нет.
  • Документы, которые читатели обычно открывают с середины. Запросы диапазона байтов позволяют клиенту сначала получить более позднюю страницу, что возможно только благодаря таблице подсказок, которую несёт линеаризованный файл.

В других случаях это не стоит усилий. Файл, открываемый с локального диска, не загружается по HTTP, поэтому нет запроса диапазона, который можно было бы использовать. Короткий документ и так отображается раньше, чем разница могла бы быть ощутима. А внутренний процесс печати ни потоково не передаёт, ни перескакивает — ему нужен весь документ, по порядку, сразу.


Подтверждение того, что результат линеаризован

Поскольку видимые страницы идентичны, «выглядит правильно» ничего не доказывает. Изменение находится в файле, поэтому проверка должна читать файл.

Линеаризованный PDF несёт словарь линеаризации ближе к началу своих байтов, а маркер представляет собой обычный текст, поэтому первых нескольких сотен байтов результата достаточно для подтверждения. И входной, и выходной файлы находятся в VFS, что делает сравнение парой операций чтения файлов:

// Read the head of the file and look for the linearization marker
const bytes = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const head = new TextDecoder('latin1').decode(bytes.slice(0, 1024));
const linearized = head.includes('/Linearized');

Это полезная защита для конвейера: преобразуйте документ, затем убедитесь, что маркер присутствует, прежде чем передавать файл дальше. Если он отсутствует, значит, файл был перезаписан чем-то ниже по потоку после линеаризации — помните, что любое повторное сохранение, включая проход сжатия, уничтожает линеаризованную структуру.


Типичные проблемы

Первая страница всё ещё появляется с задержкой. Проверьте, как доставляется файл. Линеаризация помогает только тогда, когда клиент может запрашивать части файла — при доставке по HTTP с поддержкой диапазонов. Если весь файл загружается сразу или документ короткий, этот проход не может изменить то, что вы видите.

В результате появилась лишняя строка текста. Незалицензированная сборка добавляет к документу Evaluation Warning : The document was created with Spire.PDF for JavaScript. — по одному разу на каждый вызов преобразования. Временная 30-дневная лицензия убирает её вместе с функциональными ограничениями — свяжитесь с отделом продаж, чтобы получить её.

Размер файла не уменьшился. Обычно так и будет. Линеаризация переупорядочивает существующие байты; она ничего не удаляет. Если проблема в размере, это задача сжатия, а не линеаризации.

При первом нажатии ничего не происходит. Модуль WebAssembly загружается асинхронно. В примере защитой служит if (!pdfModule) return;; в реальном интерфейсе отключайте элемент управления, пока модуль не готов, вместо показа предупреждения.


Часто задаваемые вопросы

Меняет ли линеаризация PDF его содержимое или качество? Нет. Текст, изображения, шрифты, форматирование, ссылки и метаданные переносятся в точности; меняется только внутренний порядок байтов. Страницы выглядят и ведут себя одинаково.

Линеаризация — это то же самое, что сжатие PDF? Нет. Сжатие удаляет избыточность, чтобы получить меньше байтов; линеаризация переупорядочивает уже имеющиеся байты так, чтобы первую страницу можно было прочитать раньше. Одно нацелено на объём загрузки, другое — на время до первой отрисовки.

Помогает ли это, если файл открывается с локального диска? Редко. Преимущество возникает при потоковой передаче по HTTP с запросами диапазонов, поэтому документу, открываемому по локальному пути, нечего выиграть.

Останется ли линеаризованный файл линеаризованным? Только до тех пор, пока что-нибудь его не перезапишет. Любой инструмент, повторно сохраняющий документ — проход сжатия, редактирование, объединение, — уничтожает линеаризованную структуру, поэтому линеаризация должна быть последним шагом в конвейере.

Работает ли это с зашифрованным файлом или файлом, защищённым паролем? Шифрование — это отдельный вопрос от структуры. Сначала расшифруйте документ и позвольте конвертеру работать с уже читаемым файлом.

Можно ли преобразовать несколько файлов сразу? Да. Конвертер выполняет операцию с одним файлом, поэтому пакетная обработка — это цикл: те же два члена, с отдельным именем выходного файла для каждого входного.


См. также