0

Puppeteer создание PDF из HTML

В puppeteer создание pdf возможно с помощью специального метода страницы page.pdf(). Данная функция генерирует из html разметки pdf документ.

На данный момент генерация PDF документа возможна только в режиме headless!

  1. Генерация pdf
  2. Сохранение pdf документа
  3. Печатный вид и вид экрана
  4. Отображение заголовка, подвала и фона страницы
  5. Диапазон страниц pdf
  6. Масштаб, размеры, ориентация и поля pdf
  7. Шаблоны заголовка и подвала

Генерация pdf

Для начал давайте попробуем сгенерировать pdf страницы без указания каких-либо опций в методе pdf(). Для примера сделаем pdf главной страницы PocketAdmin.tech:

const puppeteer = require('puppeteer');         // подключаем библиотеку

(async () => {                                  // объявляем функцию
  const browser = await puppeteer.launch();     // запускаем браузер
  const page = await browser.newPage();         // создаем новую вкладку
  await page.goto('https://pocketadmin.tech');  // переходим на сайт
  await page.pdf();                             // генерируем pdf текущей страницы
  await browser.close();                        // закрываем браузер
})();

Мы сгенерировали pdf страницы. Но где искать этот документ? Т.к. мы не указали никаких опций в методе pdf(), то и документ не был сохранен на нашем диске.

Сохранение PDF документа

Познакомимся с основным параметром метода pdf() – path. Данный параметр указывает путь для сохранения сгенерированного в puppeteer pdf документа.

Если путь является относительным, то он разрешается относительно текущего рабочего каталога. Если путь не указан, PDF не будет сохранен на диск!

Исправим наш первый код:

const puppeteer = require('puppeteer');         // подключаем библиотеку

(async () => {                                  // объявляем функцию
  const browser = await puppeteer.launch();     // запускаем браузер
  const page = await browser.newPage();         // создаем новую вкладку
  await page.goto('https://pocketadmin.tech');  // переходим на сайт
  await page.pdf({path: 'page.pdf'});           // генерируем pdf текущей страницы и сохраняем его в файл page.pdf
  await browser.close();                        // закрываем браузер
})();

В каталоге со скриптом у нас появился документ page.pdf. Откроем его и посмотрим результат:

puppeteer pdf print css media

Печатный вид и вид экрана

Видно, что в puppeteer генерация pdf была выполнена по нашей главной странице, но выглядит она как-то по-другому. Дело в том, что page.pdf() по умолчанию генерирует pdf для печати (print css media). Чтобы pdf был похож на оригинальную страницу необходимо перед page.pdf() вызвать page.emulateMedia(‘screen’), т.е. использовать экранный вид (screen media):

const puppeteer = require('puppeteer');         // подключаем библиотеку

(async () => {                                  // объявляем функцию
  const browser = await puppeteer.launch();     // запускаем браузер
  const page = await browser.newPage();         // создаем новую вкладку
  await page.goto('https://pocketadmin.tech');  // переходим на сайт
  await page.emulateMedia('screen');            // используем screen media
  await page.pdf({path: 'page.pdf'});           // генерируем pdf текущей страницы
  await browser.close();                        // закрываем браузер
})();

В результате этого мы получим:

puppeteer pdf screen media

Отображение заголовка, подвала и фона страницы

Да, теперь pdf документ похож на нашу главную страницу сайта. Но не хватает цветов… Условно, ответственными за “графику” (помимо screen media) можно назначить два параметра:

  1. displayHeaderFooter – выводит заголовок и подвал страницы
  2. printBackground – выводит фон страницы

При генерации pdf по умолчанию оба параметра установлены в false. Давайте установим их значение в true. Код примет следующий вид:

const puppeteer = require('puppeteer');         // подключаем библиотеку

(async () => {                                  // объявляем функцию
  const browser = await puppeteer.launch();     // запускаем браузер
  const page = await browser.newPage();         // создаем новую вкладку
  await page.goto('https://pocketadmin.tech');  // переходим на сайт
  await page.emulateMedia('screen');            // используем screen media
  await page.pdf({path: 'page.pdf', displayHeaderFooter: true, printBackground: true}); // генерируем pdf текущей страницы
  await browser.close();                        // закрываем браузер
})();

А наш документ page.pdf станет похожим на страницу сайта:

puppeteer создание pdf

Диапазон страниц pdf

Как вы заметили, в puppeteer создание pdf аналогично выполнению скриншота с параметром fullPage, т.е. полученный pdf может содержать не одну страницу (число зависит от размера страницы сайта). Чтобы ограничить число страниц или указать конкретные страницы, можно воспользоваться параметром pageRanges, например вывести только первую страницу – ‘1’, диапазон – ‘1-5’ или все сразу:

await page.pdf({path: 'page.pdf', displayHeaderFooter: true, printBackground: true, pageRanges: '1, 3-5'});

Масштаб, размеры, ориентация и поля pdf

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

  • scale – масштаб pdf страницы в диапазоне 0.1 – 2 (по умолчанию – 1)
  • landscape – ориентация страницы: false – вертикальная, true – горизонтальная (по умолчанию false)
  • format – формат страницы (по умолчанию установлено значение Letter). Возможные значения (все размеры указаны в дюймах):
    • Letter: 8.5 x 11
    • Legal: 8.5 x 14
    • Tabloid: 11 x 17
    • Ledger: 17 x 11
    • A0: 33.1 x 46.8
    • A1: 23.4 x 33.1
    • A2: 16.54 x 23.4
    • A3: 11.7 x 16.54
    • A4: 8.27 x 11.7
    • A5: 5.83 x 8.27
    • A6: 4.13 x 5.83
  • width – ширина страницы
  • height – высота страницы
  • margin – поля страницы (по умолчанию – отсутствуют):
    • top – верхнее поле
    • bottom – нижнее поле
    • left – левое поле
    • righht – правое поле

Для ширины, высоты и полей страницы можно использовать следующие величины:

  • px – пиксель
  • in – дюйм
  • cm – сантиметр
  • mm – миллиметр

По умолчанию используются пиксели:

await page.pdf({width: 1024, heigth: 768});

Если необходимо указать размеры, например в сантиметрах, то значению заключаются в кавычки:

await page.pdf({{width: '20cm', heigth: '10cm'});

Пример указания полей страницы в пикселях:

await page.pdf(
      {margin: {
          top: 80,
          bottom: 80,
          left: 30,
          right: 30,
          top: 80
          }
       });

Параметр format имеет больший приоритет над параметрами width и height.

Шаблоны заголовка и подвала

При генерации pdf из html разметки в puppeteer можно установить надписи (колонтитулы) в заголовке и подвале по шаблонам. Для этого есть два параметра:

  • headerTemplate – HTML шаблон заголовка
  • footerTemplate – HTML шаблон заголовка

Указанные параметры должны быть правильной HTML разметкой и могут содержать следующие классы:

  • date – дата
  • title – заголовок документа
  • url – адрес страницы
  • pageNumber – текущий номер страницы
  • totalPages – всего страниц в документе

Для использования headerTemplate и footerTemplate необходимо, чтобы displayHeaderFooter был установлен в значение true, а размеров полей margin должно быть достаточно для вывода надписей (колонтитулов)!

Добавим в наш pdf документ верхний колонтитул с надписью This is a PocketAdmin page с номером страницы. Приведем заключительный листинг кода по теме “Puppeteer создание pdf“:

const puppeteer = require('puppeteer');         // подключаем библиотеку

(async () => {                                  // объявляем функцию
  const browser = await puppeteer.launch();     // запускаем браузер
  const page = await browser.newPage();         // создаем новую вкладку
  await page.goto('https://pocketadmin.tech');  // переходим на сайт

  // описываем html разметку для заголовка
  html = `<div style="font-size: 15px; padding-top: 8px; text-align: center; width: 100%;">
            <span>This is a PocketAdmin page</span> - <span class="pageNumber"></span>
          </div>
        `;
  await page.emulateMedia('screen');            // используем screen media
  await page.pdf({
        path: 'page.pdf',                       // путь для сохранения pdf
        displayHeaderFooter: true,              // включаем заголовок и подвал (в данном примере обязательно!)
        printBackground: true,                  // выводим фон
        landscape: true,                        // используем горизонтальное расположение страницы
        headerTemplate: html,                   // указываем html шаблон заголовка
        margin: {                               // увеличиваем поля страницы (в данном примере обязательно!)
          top: 80,
          bottom: 80,
          left: 30,
          right: 30
          }
        });
  await browser.close();                        // закрываем браузер
})();

Результирующий pdf документ будет выглядеть следующим образом:

puppeteer pdf headerTemplate