wkhtmltopdf

wkhtmltopdf превращает подготовленную HTML-страницу в PDF с заданным форматом листа, полями, колонтитулами, нумерацией, оглавлением и активными ссылками. Пользователь управляет результатом из командной строки: указывает входной файл, параметры печати и имя документа, а для динамического содержимого настраивает ожидание JavaScript, cookies, заголовки запросов и доступ к ресурсам.

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

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

Скачать wkhtmltopdf

Оценка 9.7 Рекомендуем
  • Редактирование PDF
  • Русский интерфейс
  • Просто новичкам
Скачать бесплатно на Windows
Лучшая альтернатива
wkhtmltopdf
Оценка 8.5
  • Только командная строка
  • Старый движок CSS
  • Нет редактирования PDF
Скачать wkhtmltopdf
Загрузка начнётся после нажатия

Как устроена работа с wkhtmltopdf

У программы нет окна с панелью инструментов: роль интерфейса выполняют команда, ее параметры и сообщения в терминале. Базовая форма содержит имя исполняемого файла, входной объект и путь к PDF. Входом служит HTML-файл, адрес страницы либо стандартный поток, а выходом — имя документа или стандартный поток. Такой порядок важен: общие параметры ставят перед объектами, настройки конкретной страницы — рядом с соответствующим объектом, а имя результирующего файла завершает команду.

wkhtmltopdf input.html report.pdf

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

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

Справка wkhtmltopdf в терминале

Man-страница удобна, когда нужно быстро уточнить порядок объектов. В ней видно, что обычная страница, обложка и оглавление считаются разными объектами. Если поставить параметр не в той области, он будет проигнорирован либо применится не к той части документа, поэтому длинную команду лучше форматировать по одному аргументу в строке в сценарии сборки.

Man-страница wkhtmltopdf

Установка и проверка запуска

В Windows мастер последовательно показывает лицензию, каталог назначения и итог установки. Для обычной настройки достаточно оставить каталог внутри Program Files и завершить мастер с правами, позволяющими записать файлы. В выбранной папке находятся wkhtmltopdf.exe, связанный конвертер изображений и необходимые библиотеки; при переносе только одного EXE могут потеряться зависимости, поэтому для развертывания копируют весь предусмотренный набор.

Лицензионное соглашение в мастере wkhtmltopdf

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

Выбор каталога установки wkhtmltopdf

После завершения мастер сообщает об успешной записи компонентов. На этом этапе полезно открыть терминал заново: уже запущенные окна не всегда получают обновленную переменную PATH. Команда wkhtmltopdf --version должна вывести имя инструмента и пометку о модифицированном Qt; затем выполняют тест с небольшим HTML-файлом и проверяют, что PDF действительно появился и открывается.

Завершение установки wkhtmltopdf

Когда команда не находится по имени, добавляют каталог bin в системную или пользовательскую переменную PATH либо указывают полный путь в сценарии. Для служб и веб-серверов предпочтителен полный путь: учетная запись службы может видеть другой набор переменных, чем интерактивный пользователь. После изменения окружения службу перезапускают, иначе она продолжит работать со старым значением.

Добавление wkhtmltopdf в PATH Windows

В Linux выбирают пакет, совпадающий с семейством и выпуском дистрибутива, а не произвольный DEB или RPM. Пакетный менеджер контролирует системные зависимости и размещает бинарники в стандартном каталоге. Если установка сообщает о недостающих библиотеках шрифтов, X11 или SSL, сначала исправляют зависимости средствами дистрибутива, затем повторяют проверочную команду. Терминальная загрузка пакета позволяет увидеть перенаправление на официальный файл и фактический размер до установки.

Загрузка пакета wkhtmltopdf в терминале

В macOS установщик добавляет исполняемые файлы в системный путь, но приложение, запускаемое из веб-сервера, все равно может не наследовать пользовательское окружение. Диагностику проводят от имени той же учетной записи, которая создает отчеты. На всех системах важно проверить права на каталог временных файлов, каталог с шаблонами и папку назначения PDF: ошибка записи иногда выглядит как сбой рендера, хотя HTML загружен правильно.

Первая конвертация HTML в PDF

Для воспроизводимого результата начинают с локального файла, содержащего корректный doctype, кодировку UTF-8 и простую структуру. Команда получает два позиционных аргумента: вход и результат. Относительные пути вычисляются от текущего рабочего каталога процесса, поэтому сценарий, запущенный планировщиком или веб-сервером, может искать файлы не там, где ожидает разработчик. Надежнее заранее вычислить абсолютные пути либо явно перейти в каталог проекта.

wkhtmltopdf --encoding utf-8 input.html report.pdf

Если файл создается, но в нем пустая страница, сначала открывают тот же HTML под учетной записью процесса и проверяют доступ к стилям, изображениям и шрифтам. Затем запускают рендер без --quiet, чтобы увидеть предупреждения. Успешный вывод обычно проходит несколько этапов и заканчивается сообщением о завершении; созданный документ дополнительно проверяют утилитой, читающей сигнатуру PDF, а не только существование файла нулевого или малого размера.

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

Проверка созданного wkhtmltopdf PDF в просмотрщике

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

Подготовка HTML и печатных стилей

wkhtmltopdf отображает документ как веб-страницу, а затем размещает результат на листах. Поэтому хороший экранный шаблон не всегда является хорошим печатным шаблоном. Для отчета задают отдельные правила @media print, убирают навигацию, кнопки, всплывающие элементы и фиксированные панели, устанавливают предсказуемую ширину содержимого и контролируют разрывы страниц. Чем меньше шаблон зависит от размера окна и интерактивного состояния, тем стабильнее PDF.

Основной контейнер не стоит привязывать к высоте экрана через vh, а важные блоки — располагать абсолютными координатами без необходимости. Старые техники вроде таблиц и простого блочного потока часто дают более повторяемую пагинацию, чем сложные сетки. Flexbox поддерживается не во всех современных вариантах синтаксиса, а CSS Grid не следует считать надежной основой макета. Когда нужна двухколоночная строка с суммой и подписью, безопаснее проверить таблицу или фиксированные inline-block, чем переносить стили из современного интерфейса без адаптации.

Размеры в миллиметрах удобны для бланков, однако браузерные пиксели, масштабирование и параметр DPI влияют на итог. Не нужно одновременно компенсировать один и тот же дефект через ширину CSS, --zoom и нестандартный DPI: это усложняет поддержку. Сначала выбирают формат листа и поля, затем подгоняют ширину печатного контейнера, и лишь после этого используют масштаб как точную корректировку.

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

Разрывы страниц

Для начала новой главы применяют page-break-before: always, для завершения блока — page-break-after, а для запрета разрыва внутри компактного элемента — page-break-inside: avoid. Последнее правило не может сохранить на одном листе блок, который физически выше доступной области. В этом случае движок вынужден разорвать его или создать нежелательное пустое пространство, поэтому большие таблицы и длинные карточки нужно проектировать как последовательность переносимых строк.

Заголовок таблицы можно повторять через группу thead, но результат обязательно проверяют на реальных данных. Объединенные ячейки, вложенные таблицы и фиксированная высота строки повышают риск наложения. У длинного текста разрешают перенос, не задают строке жесткую высоту и избегают отрицательных отступов около границы листа.

Формат листа, поля и ориентация

Формат задают именем стандартного листа либо явной шириной и высотой. Для офисных отчетов чаще выбирают A4, для этикеток и чеков — собственные размеры. Одновременное указание стандартного формата и пользовательских размеров приводит к неоднозначной конфигурации, поэтому используют один способ. Единицы измерения указывают явно: миллиметры подходят для печати, дюймы — для систем с такой спецификацией, пиксели — для экраноподобных задач.

wkhtmltopdf --page-size A4 --orientation Portrait   --margin-top 15mm --margin-right 12mm   --margin-bottom 18mm --margin-left 12mm input.html report.pdf

Поля резервируют место не только для основного содержимого, но и для колонтитулов. Если верхний HTML-колонтитул имеет высоту 18 мм, поле в 10 мм приведет к наложению или обрезке. Практическая настройка начинается с заведомо достаточного поля, после чего его уменьшают по миллиметру, проверяя первую, промежуточную и последнюю страницу. Отдельный параметр расстояния между колонтитулом и текстом не заменяет поле, а работает вместе с ним.

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

DPI, масштаб и интеллектуальное уменьшение

Параметр DPI влияет на пересчет размеров и особенно заметен в системах, где исходный шаблон подогнан под конкретное разрешение. --zoom масштабирует страницу, а интеллектуальное уменьшение пытается вместить широкое содержимое автоматически. Эти механизмы могут маскировать ошибочную ширину шаблона, но затем дают различный размер текста на страницах. Для строгих бланков разумно отключить автоматическое уменьшение и исправить CSS; для архивной копии произвольной страницы автоматическая подгонка иногда полезнее.

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

Шрифты, кириллица и кодировки

Кириллица корректно печатается, когда HTML объявляет UTF-8, файл действительно сохранен в этой кодировке, а выбранный шрифт содержит нужные символы. Параметр --encoding utf-8 помогает странице без корректного заголовка, но не исправляет текст, уже поврежденный при чтении из базы данных. Если вместо букв появляются знаки вопроса, сначала сохраняют исходный HTML и проверяют его обычным текстовым редактором.

Движок использует шрифты, доступные учетной записи процесса. На сервере может не быть гарнитуры, установленной на компьютере дизайнера, поэтому сработает подмена с другими метриками: изменится ширина строк, высота таблиц и пагинация. Для предсказуемости выбирают распространенную гарнитуру, устанавливают ее на все узлы генерации либо подключают файл шрифта через @font-face, соблюдая права на распространение.

Локальный файл шрифта подчиняется тем же ограничениям доступа, что изображения и стили. Нужно включить чтение локальных ресурсов и разрешить нужный каталог, а не открывать весь диск. Путь в CSS лучше формировать абсолютным и не смешивать обратные и прямые слеши. После изменения шрифтового кэша процесс генерации перезапускают; в Linux при необходимости обновляют fontconfig.

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

Жирность 600 или 800 не появится из обычного файла автоматически во всех случаях. Когда подключен только normal, движок может синтетически утолщать контур, и результат отличается от браузера. Для документов, где внешний вид важен юридически или брендово, подключают отдельные файлы normal, bold и italic и проверяют встраивание шрифтов анализатором PDF.

Изображения, SVG и локальные ресурсы

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

wkhtmltopdf --enable-local-file-access   --allow assets input.html report.pdf

Безопаснее создать временный каталог с копиями нужных изображений, чем давать доступ к общему хранилищу. После генерации каталог удаляют. Имена файлов нормализуют, пробелы и национальные символы кодируют последовательно, а пути не формируют прямой конкатенацией пользовательского ввода. Если шаблон поступает извне, параметр доступа не должен превращать HTML в средство чтения произвольных файлов.

JPEG подходит для фотографий, PNG — для схем и прозрачности, SVG — для векторных логотипов и графиков. Однако сложные SVG с фильтрами, внешними шрифтами или современными возможностями могут отображаться иначе. Для критичного элемента полезно заранее упростить SVG, перевести текст в контуры в разрешенных условиях или подготовить PNG нужного размера. Формат WebP нельзя считать надежным для этого движка; ресурс лучше конвертировать в PNG или JPEG до запуска.

Параметры качества изображения и предельного DPI позволяют уменьшить PDF. Слишком агрессивное снижение делает мелкий текст на сканах и штрихкоды нечитаемыми, поэтому качество оценивают на распечатке и при увеличении. Для фотоотчета можно уменьшить JPEG, а логотипы, QR-коды и диаграммы оставить без повторного сжатия или передать как вектор.

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

JavaScript и динамическое содержимое

JavaScript включен для страниц, которым он нужен, но команда не знает, когда приложение действительно закончило отрисовку. Простая задержка задается в миллисекундах и отсчитывается после загрузки страницы. Она подходит для небольшого графика или шаблона с предсказуемым временем, однако фиксированные пять секунд будут напрасно замедлять быстрые задания и не спасут редкий медленный запрос.

wkhtmltopdf --javascript-delay 1500 dashboard.html dashboard.pdf

Более надежный вариант — сигнал готовности через --window-status. Скрипт страницы устанавливает определенное значение window.status после получения данных, построения графиков и применения классов печати, а wkhtmltopdf ждет именно его. Нужно предусмотреть тайм-аут на стороне вызывающего процесса: если скрипт упал до сигнала, задача не должна занимать рабочий процесс бесконечно.

--run-script выполняет дополнительный код после загрузки. С его помощью можно раскрыть свернутые блоки, убрать панель управления или добавить класс к body. Команда становится уязвимой к ошибкам кавычек, поэтому длинную логику лучше поместить в сам шаблон, а параметром запускать короткую функцию. Для диагностики включают вывод JavaScript и смотрят сообщения консоли; без этого ошибка библиотеки часто проявляется только пустым графиком.

Современные одностраничные приложения могут использовать синтаксис JavaScript и API, которых нет во встроенном WebKit. Полифилл помогает лишь для части функций; он не добавляет полноценную поддержку современного движка разметки. Для отчетов выгоднее сделать отдельный серверный шаблон с готовыми данными, чем печатать интерактивный интерфейс целиком. Canvas следует дождаться после отрисовки, а внешние модули и динамический import могут потребовать переработки.

Параметр остановки медленных сценариев защищает от зависания, но иногда прерывает тяжелую визуализацию. Отключать эту защиту без внешнего тайм-аута рискованно. В производственной очереди ограничивают время процесса, память и число параллельных запусков, а после принудительного завершения удаляют частично созданный PDF.

Колонтитулы, номера страниц и служебные поля

Для короткого текста используются параметры левой, центральной и правой области верхнего или нижнего колонтитула. В строку можно вставлять маркеры текущей страницы, общего числа страниц, заголовка, даты, времени и адреса документа. Такой способ проще HTML-файла и подходит для номера страницы, названия отчета и даты формирования.

wkhtmltopdf --footer-center "Страница [page] из [topage]"   --footer-font-size 9 --footer-spacing 4 input.html report.pdf

HTML-колонтитул нужен для логотипа, таблицы реквизитов или сложной сетки. Он загружается как отдельная страница, поэтому его CSS, шрифты и изображения должны быть доступны независимо. Параметры страницы передаются в строке запроса; небольшой сценарий читает их и подставляет номер, дату или заголовок в отмеченные элементы. Не стоит подключать к колонтитулу весь пакет стилей сайта: это замедляет каждую страницу и повышает риск неожиданного отступа.

Высота колонтитула напрямую связана с полями. Если содержимое перекрывает основной текст, увеличивают верхнее или нижнее поле, а затем настраивают spacing. Если колонтитул обрезан, проверяют фиксированную высоту body, внутренние margin и размер изображения. Тестируют страницы с однозначными номерами — первую, девятую, десятую, последнюю — потому что изменение количества цифр может сдвинуть центрирование.

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

Обложка по правилам объекта не получает обычные колонтитулы и не попадает в автоматическое оглавление. Это удобно для титульного листа. Если нужен номер начиная не с единицы, используют смещение страниц, но проверяют значения маркеров в колонтитулах и ссылках оглавления на полном документе.

Обложка, оглавление и несколько HTML-объектов

Один PDF можно собрать из последовательности объектов. Команда сначала получает глобальные параметры, затем обложку, обычные страницы и объект toc, а в конце — имя результата. Порядок в командной строке становится порядком в документе. Это позволяет объединить титульный лист, основной отчет и приложение без промежуточного слияния PDF.

wkhtmltopdf cover cover.html toc chapter1.html chapter2.html book.pdf

Автоматическое оглавление строится по заголовкам HTML и внутреннему outline. Его глубину ограничивают, чтобы служебные H4 и H5 не превратились в длинный список. Точки-лидеры, отступы и шрифты управляются XSLT. Для настройки сначала выгружают стандартный XSL, сохраняют копию в проекте и меняют только необходимые шаблоны; так легче увидеть, какое правило повлияло на номер страницы или уровень заголовка.

Заголовки должны иметь логическую иерархию. Если визуальный стиль требует мелкий H2, его размер меняют CSS, а не заменяют на H5. Иначе оглавление и закладки будут отражать оформление, а не структуру. Заголовок, скрытый через display:none, обычно не должен участвовать в навигации; для служебных секций лучше использовать обычный div.

PDF-outline создает дерево закладок в просмотрщике. Его можно включать, ограничивать глубину или выгружать в XML для диагностики. Если пункты оглавления ведут на неверные страницы, проверяют разрывы, скрытые заголовки и изменение масштаба между объектами. После настройки обязательно открывают документ в просмотрщике, который показывает панель закладок, а не оценивают только печатный вид.

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

Ссылки, формы и интерактивность PDF

Внутренние HTML-ссылки могут стать переходами внутри PDF, а внешние — активными областями, которые откроет просмотрщик. Для отчетов это полезно в оглавлении, списке приложений и перекрестных ссылках. Если политика документа запрещает активные адреса, соответствующую возможность отключают. Визуальное подчеркивание ссылки задается CSS независимо от того, будет ли область кликабельной.

Якорь должен существовать в итоговой разметке до запуска печати. Динамически созданный идентификатор появится только после успешного выполнения JavaScript. При нескольких объектах одинаковые id могут вести не туда, поэтому используют уникальные префиксы. После генерации проверяют не только цвет текста, но и фактическую область ссылки: абсолютное позиционирование и трансформации иногда смещают кликабельный прямоугольник.

HTML-формы можно перенести в PDF как поля, если эта возможность включена и разметка достаточно проста. Однако wkhtmltopdf не заменяет редактор форм: сложные вычисления, валидация, подписи и сценарии AcroForm требуют отдельного инструмента. Для архивного документа формы обычно отключают или превращают в обычный текст, чтобы состояние полей не зависело от просмотрщика.

Чекбоксы и радиокнопки в печатной форме лучше стилизовать так, чтобы отмеченное состояние было видно даже после растрирования или отключения интерактивности. Значение поля выводят рядом текстом, а не полагаются только на внешний вид системного контрола. Это особенно важно для черно-белой печати и долгосрочного хранения.

Cookies, заголовки, авторизация и POST-запросы

Закрытая страница часто возвращает форму входа вместо отчета. wkhtmltopdf умеет передавать cookies, пользовательские HTTP-заголовки, базовую авторизацию и данные POST. Выбирают минимальный механизм, который уже используется приложением. Для сессионного сайта обычно достаточно короткоживущей cookie, а для внутренней конечной точки — отдельного токена с правом только на чтение отчета.

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

Cookie-jar позволяет прочитать и сохранить cookies между запросами. Файл размещают в защищенном временном каталоге, задают права только владельцу и удаляют после задания. Не используют общий jar для разных клиентов: это создает риск смешения сессий. Имя временного файла генерируют случайно и не принимают из параметров запроса.

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

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

Прокси, сеть и обработка ошибок загрузки

Прокси задают схемой, адресом, портом и при необходимости учетными данными. Отдельно можно перечислить узлы, которые следует открывать напрямую. Проверку начинают с простой страницы без авторизации, затем добавляют защищенные ресурсы. Ошибка DNS, TLS и запрет прокси выглядят похоже — основное содержимое может открыться, а изображения останутся пустыми, поэтому журнал загрузки должен сохраняться вместе с кодом возврата.

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

Сетевой тайм-аут полезно контролировать на двух уровнях. Внутренние настройки ограничивают отдельные операции, а вызывающий процесс задает общий предел всей задачи. После превышения предела сначала отправляют мягкое завершение, затем принудительное; выходной файл с временным именем удаляют и не публикуют пользователю.

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

Для повторяемых заданий сетевые ресурсы кэшируют на уровне приложения, но не полагаются на неявный браузерный кэш. Каждому отчету передают окончательные изображения и стили с известными хешами. Это позволяет повторно создать документ даже после изменения исходного сайта.

Пакетная обработка и чтение аргументов из потока

При массовой генерации не обязательно запускать оболочку с огромной командной строкой. Режим чтения аргументов из стандартного ввода принимает по одной строке задания и позволяет повторно использовать процесс для множества преобразований. Строки разбираются по правилам командной строки, поэтому пробелы в путях по-прежнему требуют корректного экранирования.

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

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

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

Логирование команды

В журнал записывают путь к бинарнику, безопасные аргументы, длительность, код возврата, размер PDF и идентификатор шаблона. Cookies, пароли, токены и персональные POST-данные маскируют. Полную команду для отладки можно собрать в защищенном журнале с коротким сроком хранения, но она не должна попадать в публичный ответ веб-сервера.

Интеграция с PHP, Python, Node.js и другими системами

Обертка на языке программирования обычно не содержит движок рендеринга: она строит массив аргументов, запускает wkhtmltopdf, передает HTML и читает результат. Поэтому первая диагностика всегда выполняется прямой командой от имени того же пользователя. Если прямой запуск работает, а библиотека нет, сравнивают путь к бинарнику, рабочий каталог, окружение, права, экранирование и тайм-аут.

Нельзя собирать строку команды конкатенацией пользовательских значений. Имя файла, формат листа и адрес должны проходить белый список, а процесс следует запускать API, принимающим массив аргументов без оболочки. Это предотвращает подстановку дополнительных ключей и системных команд. Даже безопасный массив не отменяет проверку HTML: страница способна обращаться к сети и локальным ресурсам.

В PHP часто различается PATH интерактивной консоли и php-fpm. В конфигурации указывают полный путь и проверяют доступ пользователя пула к временной папке. В Python применяют subprocess без shell=True, передают bytes через stdin и устанавливают timeout. В Node.js используют spawn, а не exec с ограниченным строковым буфером; stdout в режиме выдачи PDF обрабатывают как бинарный поток.

При передаче HTML через stdin нужно закрыть поток, иначе wkhtmltopdf продолжит ждать данные. stderr читают параллельно, чтобы заполненный буфер не заблокировал процесс. Если PDF возвращается через stdout, диагностические сообщения оставляют в stderr и не преобразуют в текст. Для больших документов поток записывают прямо во временный файл, не удерживая весь результат в памяти.

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

Контейнер должен включать бинарник, его библиотеки, шрифты и сертификаты. Одного копирования EXE или ELF недостаточно. Образ фиксируют по контрольной сумме, а тестовый набор PDF сравнивают после изменения базового образа: обновление fontconfig или шрифтов способно изменить переносы даже без изменения шаблона.

Безопасная генерация документов

HTML следует считать активным входом, а не безобидным текстом. Он может запускать JavaScript, отправлять сетевые запросы и при разрешенном доступе читать файлы. Поэтому непроверенную разметку не передают в процесс с широкими правами. Шаблоны хранят в доверенном репозитории, пользовательские поля экранируют, а разрешенные теги и атрибуты фильтруют.

Процесс запускают под отдельной учетной записью без доступа к ключам, конфигурации и домашним каталогам. Файловая система предоставляет только шаблон, временные ресурсы и каталог результата. На Linux применяют профиль AppArmor или SELinux, ограничения пространства имен и read-only mounts; на других системах используют сопоставимые механизмы изоляции.

Сетевой доступ ограничивают до нужных внутренних узлов. Если отчет полностью самодостаточен, сеть отключают. Это одновременно повышает безопасность и воспроизводимость. Для шаблонов, которым нужен API, создают промежуточную конечную точку с минимальными данными и короткоживущим токеном, а не открывают генератору всю внутреннюю сеть.

Ресурсные лимиты защищают от огромного DOM, изображений гигантского разрешения, бесконечного JavaScript и чрезмерного количества страниц. Ограничивают размер входа, число изображений, суммарный объем ресурсов, память, процессорное время и максимальную продолжительность. После аварии проверяют дочерние процессы и удаляют временные каталоги.

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

Управление качеством и размером PDF

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

Предел DPI уменьшает растровые изображения, которые имеют избыточное разрешение. Для обычного текста DPI картинки не важен, поскольку текст рисуется векторно; для сканированной страницы снижение может уничтожить мелкие детали. Создают несколько профилей: экранный отчет, печатный документ и архивный вариант, затем измеряют размер и визуальное качество на одинаковом наборе.

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

Отключение фонов уменьшает файл, если шаблон использует большие декоративные блоки. Однако белый текст на цветном фоне станет невидимым. Печатная таблица должна сохранять контраст без фоновой заливки или иметь отдельные правила. Опцию применяют после просмотра всех типов страниц, а не только титула.

Сжатие PDF можно отключить для диагностики, но обычный результат лучше оставлять сжатым. Повторное прогоняние готового файла через случайный оптимизатор способно повредить ссылки, формы или шрифты. Если требуется PDF/A, цифровая подпись, шифрование или линейризация, эти операции выполняют отдельным специализированным инструментом после генерации и проверяют валидатором.

Производительность и параллельные задания

Время рендера зависит от числа страниц, количества сетевых запросов, JavaScript, размеров картинок и сложности CSS. Измерять нужно этапы: подготовку HTML, загрузку ресурсов, работу wkhtmltopdf и последующую обработку. Иначе оптимизация шаблона не поможет, если основное ожидание происходит в медленном API.

Параллелизм ограничивают числом ядер и памятью. Один тяжелый отчет способен занять сотни мегабайт, поэтому запуск десятков процессов одновременно вызывает обмен с диском и увеличивает задержку каждого. Очередь поддерживает небольшой пул работников и регулирует его на основании реальных пиков, а не среднего размера счета.

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

JavaScript-задержка должна быть минимально необходимой. Сигнал готовности лучше фиксированного ожидания. Если графики строятся из данных, можно заранее получить их на сервере и вставить SVG, исключив браузерные запросы. Длинный DOM разбивают на логические объекты только тогда, когда это не нарушает оглавление и нумерацию.

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

Совместимость с HTML, CSS и веб-технологиями

Рендер основан на Qt WebKit, поэтому ожидаемая поддержка ближе к браузерам прежнего поколения, чем к современному Chromium. Базовый HTML, таблицы, float, абсолютное позиционирование, фоновые изображения и традиционные печатные правила работают предсказуемо. Новые свойства следует проверять отдельно, а не переносить таблицу совместимости современного браузера.

CSS Grid, современные варианты flex, переменные CSS, сложные фильтры, sticky-позиционирование и часть новых селекторов могут не сработать или дать другое расположение. Для отчета создают слой совместимости: вычисленные цвета подставляют как обычные значения, grid заменяют таблицей или блоками, sticky убирают, а интерактивные состояния раскрывают заранее.

Медиа-запросы выбираются в зависимости от режима печати. Параметр использования print media помогает применить печатный набор, но шаблон не должен предполагать, что все экранные правила исчезнут. Специфичность CSS, порядок подключения и !important действуют как обычно. Для диагностики сохраняют отдельный минимальный HTML и постепенно возвращают стили.

Ширина viewport влияет на адаптивный макет. Если страница переключается на мобильную колонку, задают подходящий размер окна или делают печатный CSS независимым от экранных breakpoint. Изменение viewport может повлиять и на JavaScript, читающий размеры элементов. После выбора значения его фиксируют в конфигурации, чтобы разные серверы не получали разные макеты.

SVG, canvas и изображения требуют отдельной проверки. Canvas является растром состояния в момент печати; если он еще пуст, PDF останется пустым. Видео, WebGL и интерактивные карты не предназначены для прямой печати — их заменяют статическим кадром, серверной картой или заранее построенной диаграммой.

Типичные ошибки и способы устранения

Команда не найдена

Проверяют полный путь к бинарнику, PATH именно у учетной записи процесса и разрядность пакета. После изменения окружения перезапускают терминал, службу или пул веб-сервера. В конфигурации обертки указывают файл wkhtmltopdf, а не каталог и не связанный wkhtmltoimage.

Локальные файлы заблокированы

Включают локальный доступ и перечисляют разрешенный каталог. Затем проверяют абсолютные пути, права и существование файлов. Не используют широкое разрешение корня диска. Если ресурс расположен рядом с HTML, убеждаются, что рабочий каталог не влияет на относительную ссылку.

Изображения или стили не загружаются

Отключают тихий режим, читают предупреждение о протоколе или коде ответа, открывают ресурс от имени процесса. Для защищенного адреса передают cookie или заголовок, для самоподписанного сертификата устанавливают доверенный корень. Формат WebP заменяют на PNG или JPEG.

Пустой график

Включают отладку JavaScript, добавляют сигнал готовности или задержку, проверяют синтаксис, поддерживаемый движком. Убирают ленивую загрузку и анимацию, задают явный размер контейнера. Если библиотека требует современного API, строят SVG на сервере или выбирают Chromium-инструмент.

Колонтитул перекрывает текст

Увеличивают поле соответствующей стороны, затем регулируют spacing. Убирают margin у body колонтитула и проверяют высоту логотипа. HTML-фрагмент делают коротким и не подключают глобальные стили приложения.

Таблица разрывается неправильно

Удаляют фиксированные высоты строк, разрешают перенос текста, упрощают rowspan и вложенные таблицы. Заголовок оформляют через thead, а компактные строки защищают page-break-inside. Большой блок, превышающий лист, делят на части на уровне шаблона.

Текст стал слишком мелким

Проверяют ширину основного контейнера, smart shrinking, zoom и DPI. Оставляют один механизм масштаба, исправляют широкие элементы и задают формат листа. Не компенсируют проблему одновременным увеличением шрифта и уменьшением zoom.

Разные переносы на серверах

Сравнивают установленные шрифты, fontconfig, локаль, версии библиотек и параметры запуска. Контейнеризуют среду, фиксируют файлы шрифтов и прогоняют эталонные документы. Даже одинаковый HTML меняет пагинацию при другой метрике шрифта.

Процесс завершается с кодом 1, но PDF существует

Не считать файл автоматически успешным. Сохраняют stderr, выясняют, какой ресурс вызвал сетевую ошибку, и проверяют структуру PDF. Политика приложения решает, допустим ли пропущенный второстепенный ресурс; критический отчет отклоняют.

Сообщение о немодифицированном Qt

Такая сборка может не поддерживать несколько объектов, оглавление, колонтитулы и часть печатных параметров. Проверяют вывод версии и заменяют пакет на сборку, для которой заявлен модифицированный Qt. Установка одноименного пакета из репозитория дистрибутива не всегда дает тот же набор возможностей.

Не удается записать PDF

Проверяют права каталога, свободное место, длину пути и блокировку существующего файла. Пишут во временное уникальное имя, затем атомарно переименовывают. На Windows просмотрщик может удерживать файл открытым, поэтому не перезаписывают документ, который уже отдан пользователю.

Зависание и высокий расход памяти

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

Проверка результата перед выдачей пользователю

Факт создания файла недостаточен. Минимальная автоматическая проверка читает первые байты PDF, убеждается в ненулевом размере и корректном завершении процесса. Для важных документов анализатор дополнительно получает число страниц, размер листов, наличие шрифтов и отсутствие поврежденных объектов.

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

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

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

Связанный инструмент wkhtmltoimage

В комплекте используется отдельная команда wkhtmltoimage для сохранения HTML в PNG, JPEG и другие растровые форматы. Она полезна для превью отчета, снимка длинной страницы и диагностики рендера без пагинации. Не следует подменять ею wkhtmltopdf: изображение не содержит выбираемого текста, закладок и многостраничной структуры PDF.

Справка wkhtmltoimage содержит параметры ширины, высоты, качества, формата и области обрезки. Для снимка задают viewport, ждут JavaScript и при необходимости ограничивают прямоугольник. Высота ноль означает автоматический расчет по странице; на очень длинном документе это может создать огромное изображение, поэтому ввод ограничивают.

Справка wkhtmltoimage в терминале

Практический запуск показывает терминал и открытый результат. Такой кадр помогает проверить, что WebKit видит страницу и ресурсы. Если изображение правильное, а PDF ломается, проблема вероятнее связана с пагинацией, полями или колонтитулами; если оба результата пусты, ищут ошибку загрузки или JavaScript.

Результат работы wkhtmltoimage

Для каталожного превью изображение лучше строить из уже готового PDF отдельным PDF-рендерером, чтобы оно точно соответствовало документу. wkhtmltoimage применяют, когда нужен снимок HTML до печати или самостоятельная картинка страницы.

Практические сценарии

Счет из серверного шаблона

Приложение получает данные заказа, экранирует поля и формирует самодостаточный HTML. Логотип и шрифт копируются в временный каталог, доступ разрешается только ему. Команда задает A4, поля, номер страницы и UTF-8. Результат пишется во временное имя, проверяется, затем перемещается в хранилище; каталог ресурсов удаляется.

Длинный управленческий отчет

Отчет делится на обложку, оглавление, главы и приложение. Заголовки образуют корректную иерархию, таблицы не имеют жесткой высоты, для альбомного приложения запускается отдельная генерация с последующим объединением специализированным PDF-инструментом. Графики передаются как SVG, поэтому не требуется ждать тяжелую клиентскую библиотеку.

Печать защищенной внутренней страницы

Система создает одноразовый токен с коротким сроком и правом на конкретный отчет. wkhtmltopdf получает его в cookie только для внутреннего домена. Ресурсы с внешних доменов запрещены, журнал маскирует cookie, процесс имеет сетевой доступ лишь к приложению. После генерации токен аннулируется.

Архивная копия страницы

Перед печатью приложение сохраняет HTML и все ресурсы с контрольными суммами. Скрипт раскрывает скрытые секции, отключает анимацию и ждет сигнал готовности. PDF получает дату, название и нумерацию. На длительное хранение помещаются PDF, входной пакет и параметры, что позволяет объяснить отличие от страницы, изменившейся позже.

Пакет документов по списку клиентов

Очередь создает отдельное задание на клиента, ограничивает число работников и не передает персональные данные через командную строку. Каждый PDF имеет случайное временное имя и затем получает отображаемое имя в базе. Ошибки шаблона не повторяются автоматически, сетевые сбои имеют ограниченное число попыток.

Отчет с диаграммами

Данные встраиваются в HTML как безопасный JSON, сценарий строит SVG и устанавливает window.status. Команда ждет статус, а внешний процесс завершает задачу по тайм-ауту. Для каждого графика задана фиксированная ширина и высота, легенда не зависит только от цвета, а анимация отключена.

Этикетка нестандартного размера

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

Черновик для последующего редактирования

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

Порядок параметров и разрешение конфликтов

Длинная команда становится надежной, когда параметры разделены по области действия. Глобальные ключи задают свойства всего PDF: количество копий, сортировку, ориентацию, формат листа, DPI, поля, качество изображений, уровень журнала и заголовок документа. Параметры страницы управляют загрузкой конкретного HTML, JavaScript, фонами, ссылками, локальными файлами и колонтитулами. Настройки оглавления относятся только к объекту toc. Если глобальный ключ поставить после первого объекта, парсер может воспринять его как параметр страницы или сообщить об ошибке.

Опции обрабатываются слева направо, но не все из них можно безопасно повторять. Для одного объекта последнее значение обычно заменяет предыдущее, а повторяющиеся cookies, заголовки, разрешенные каталоги и POST-поля накапливаются. Генератор команды должен различать скалярный параметр и список, иначе второй заголовок случайно уничтожит первый или старое значение останется рядом с новым.

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

Короткие ключи удобны для ручного запуска, а полные названия — для конфигурации и документации. Команда с -T 15mm компактна, но --margin-top 15mm понятнее при ревью. В сценариях используют единый стиль, сортируют параметры по смысловым блокам и оставляют комментарий, почему выбрано необычное значение zoom или delay.

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

Стандартный ввод, стандартный вывод и конвейеры

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

PDF можно получить через stdout, указав дефис вместо имени результата. Такой режим подходит для немедленной отправки клиенту или записи в объектное хранилище. Поток является бинарным; преобразование в строку, добавление перевода строки или объединение с журналом повреждает документ. stderr читается отдельно, а HTTP-заголовки формирует веб-приложение, не wkhtmltopdf.

generate-html | wkhtmltopdf - - > report.pdf

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

При большом HTML отправитель и wkhtmltopdf работают с обратным давлением: запись приостанавливается, когда читающая сторона не успевает. API процесса должно поддерживать потоковую передачу, а не накапливать весь документ в нескольких копиях памяти. Одновременно читают stderr, иначе заполненный канал сообщений может остановить обе стороны.

Стандартный поток особенно полезен для секретных данных: содержимое не появляется в имени файла и не сохраняется автоматически на диске. Однако его все равно могут увидеть дампы памяти и журналы приложения. Обработчик ошибок не должен записывать полный HTML с персональными сведениями; для диагностики сохраняют обезличенную копию или хеш входа.

Метаданные, копии и свойства готового документа

Заголовок PDF можно задать параметром title; если он не указан, значение может браться из HTML. Заголовок отображается в свойствах просмотрщика и иногда используется как имя вкладки, поэтому для отчета лучше передать понятное значение без персональных секретов. Автор, тема, ключевые слова и расширенная XMP-разметка не являются основной областью настройки wkhtmltopdf; их добавляют последующей PDF-обработкой, когда это требуется архивным регламентом.

Параметр copies формирует несколько копий внутри одного PDF. Collate определяет порядок: при двухстраничном документе сортированный вариант дает страницы 1–2, 1–2, а несортированный — 1–1, 2–2. Для электронной выдачи копии обычно не нужны; печатная система надежнее управляет тиражом сама. Если копии создаются в PDF, размер и число страниц увеличиваются, что учитывают в проверках.

Ориентация и формат относятся ко всему выходу в пределах одного запуска глобальной настройки. Когда часть отчета должна быть книжной, а часть альбомной, проще создать два PDF и объединить их инструментом, который сохраняет закладки и ссылки. Попытка повернуть широкую таблицу CSS-трансформацией затрудняет расчет размеров и часто обрезает область.

Функция grayscale переводит вывод в оттенки серого. Она полезна для печатного профиля, но не гарантирует оптимальный контраст. Светло-желтый и светло-зеленый могут стать близкими тонами, а цветной логотип потерять детали. Перед включением создают отдельный тест и при необходимости заменяют цвета в печатном CSS.

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

Создание собственного HTML-колонтитула

Файл колонтитула делают отдельным минимальным документом с doctype, UTF-8 и встроенным CSS. В body размещают таблицу или три блока для левой, центральной и правой областей. Внешние margin обнуляют, высоту задают содержимым, а размер текста — в пунктах или пикселях после печатной проверки. Тяжелые фреймворки, веб-шрифты с удаленного сервера и общие скрипты приложения из колонтитула исключают.

Движок добавляет к адресу параметры вроде page, topage, date, time, title, web page и section. Небольшой сценарий разбирает строку запроса и записывает значения в элементы с соответствующими классами. Он должен корректно декодировать символы и работать без современных API. Поскольку колонтитул повторяется на каждой странице, ошибка сценария умножается на весь документ.

Для логотипа выбирают SVG с простыми конструкциями или PNG точного размера. Изображение не должно загружаться с пользовательского сайта при каждом листе. Его размещают рядом с колонтитулом и разрешают каталог. Фиксированная ширина предотвращает скачок высоты после загрузки.

Проверка начинается с цветной рамки вокруг body и явного номера страницы. Рамка показывает фактическую область, отступы и обрезку. После настройки рамку удаляют. Если между колонтитулом и содержимым остается слишком много воздуха, уменьшают spacing и поле последовательно, а не добавляют отрицательный margin.

Разные колонтитулы для разных глав в одном запуске требуют настройки на уровне объектов. Для простоты часто создают отдельные PDF по разделам и объединяют их, особенно если обложка, основная часть и приложение имеют разные требования. При объединении заново проверяют нумерацию и закладки: номера, вычисленные внутри отдельных файлов, не знают общего количества страниц.

Настройка автоматического оглавления через XSLT

Объект toc не является обычной HTML-страницей: wkhtmltopdf сначала строит outline, затем применяет XSLT к XML-структуре и печатает получившийся HTML. Поэтому изменение CSS основного документа не всегда меняет оглавление. Базовый шаблон выгружают командой dump-default-toc-xsl и сохраняют как исходник рядом с проектом.

В XSLT определяют строку пункта, уровень вложенности, отступ, стиль номера и лидирующие точки. Изменения вносят небольшими шагами. Ошибка пространства имен или XPath может создать пустое оглавление без очевидного объяснения, поэтому сначала проверяют неизмененный выгруженный файл, затем меняют одно правило и сравнивают результат.

Параметр depth ограничивает число уровней. Для технического руководства обычно достаточно двух или трех: раздел, подраздел, иногда процедура. Включение всех заголовков делает оглавление длиннее самого полезного текста. Служебные заголовки исключают структурой HTML, а не визуальным скрытием после построения outline.

Текст заголовка поступает из документа. Номер главы, добавленный CSS-счетчиком через псевдоэлемент, может не попасть в outline, поэтому важную нумерацию формируют в самом тексте или XSLT. Длинные заголовки должны переноситься, не сталкиваясь с номером страницы. Для этого номер размещают в отдельной области, а пункту задают правый запас.

Оглавление проверяют после всех изменений полей, шрифтов и масштаба. Эти параметры меняют пагинацию, а значит, и номера. В автоматическом тесте выбирают несколько известных заголовков в начале, середине и конце, проверяют видимый номер и фактический переход ссылки.

Развертывание в службе и контейнере

Служебный процесс работает в другом окружении, чем пользовательский терминал. У него могут отсутствовать домашний каталог, DISPLAY, прокси, локаль, PATH и доступ к пользовательским шрифтам. Конфигурация должна явно задавать путь к бинарнику, рабочий каталог, временную папку и необходимые переменные. Проверочный запуск выполняют от имени службы, а не администратора.

В контейнер включают системные библиотеки, сертификаты, fontconfig и конкретные файлы шрифтов. Минимальный образ без этих компонентов может запускать бинарник, но выдавать квадраты вместо символов или ошибки TLS. После сборки образа выполняют smoke-test с кириллицей, SVG, защищенным ресурсом и колонтитулом.

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

Временный каталог монтируют с ограниченным размером и без исполнения файлов, если это поддерживает система. Каждый запрос получает собственную подпапку с правами владельца. Очистка выполняется и после успеха, и после исключения, и после принудительного завершения. Периодическая задача удаляет осиротевшие папки старше допустимого времени.

Проверка здоровья службы не должна запускать тяжелый отчет. Достаточно короткого HTML, который создает одностраничный PDF с известным текстом. Глубокая проверка по расписанию генерирует полный эталон, анализирует шрифты и колонтитулы. Метрики очереди включают длительность, использование памяти, процент ошибок загрузки и число принудительных завершений.

Сравнение wkhtmltopdf с аналогами

ПрограммаЛучше подходит дляГлавное ограничение
wkhtmltopdfАвтоматической печати стабильных HTML-шаблонов, отчетов с колонтитулами и оглавлениемСовременный CSS и JavaScript поддерживаются не полностью
PDF CommanderРучного редактирования, перестановки страниц, подписей и правок уже созданного PDFНе предназначен для серверного рендера HTML по команде
WeasyPrintПечатных документов на HTML и CSS с сильным упором на paged mediaJavaScript страницы не выполняется
PuppeteerДинамических сайтов и отчетов, которым нужен современный ChromiumТребует управления браузером и его ресурсами
PlaywrightКросс-браузерной автоматизации и печати страниц после сложных сценариевPDF обычно формируется через Chromium, а настройка тяжелее простой команды
PrinceИздательской верстки, сложной пагинации и профессионального CSS для печатиДля большинства коммерческих применений нужна платная лицензия

wkhtmltopdf разумно выбирать для уже отлаженных шаблонов, которым достаточно классического WebKit и нужна простая автоматизация. WeasyPrint удобнее для документов без JavaScript с современными правилами печатного CSS; Puppeteer или Playwright — для приложений, зависящих от актуального браузерного движка. Prince оправдан в издательских задачах, а PDF Commander нужен после генерации, когда документ требуется исправить вручную, объединить, подписать или перестроить.

Контрольный список настройки

  • Проверить прямой запуск и наличие пометки о модифицированном Qt.
  • Зафиксировать полный путь к бинарнику в конфигурации службы.
  • Подготовить отдельные печатные стили без неподдерживаемых конструкций.
  • Установить одинаковые шрифты на всех рабочих узлах.
  • Разрешить доступ только к каталогу ресурсов конкретного задания.
  • Выбрать формат листа, поля и пространство под колонтитулы.
  • Заменить фиксированную задержку JavaScript сигналом готовности, где это возможно.
  • Ограничить сеть, память, время процесса и число параллельных запусков.
  • Писать результат во временное имя и проверять PDF перед публикацией.
  • Сохранять безопасный stderr, код возврата, длительность и размер документа.
  • Прогонять эталонные шаблоны после изменения среды или шрифтов.
  • Не передавать непроверенный HTML процессу с доступом к секретам и файловой системе.

Настроенная цепочка должна давать одинаковую пагинацию на повторных запусках, явно сообщать о недоступных ресурсах и не публиковать частичный файл. Основные усилия приходятся не на саму команду, а на дисциплину печатного шаблона: контролируемые шрифты, предсказуемые размеры, завершенный JavaScript и ограниченный доступ к ресурсам превращают HTML в устойчивый PDF-процесс.

Перед вводом в эксплуатацию создают набор документов с крайними значениями: пустыми таблицами, максимальной длиной строк, большим количеством страниц, отсутствующей необязательной картинкой и временно недоступным ресурсом. Для каждого случая заранее определяют ожидаемый код, допустимость результата и сообщение пользователю. Такой тест показывает, где wkhtmltopdf должен продолжить работу, а где задача обязана завершиться ошибкой, и завершает настройку воспроизводимой генерации.