Screenshot, созданный Steve Bauman, позволяет преобразовывать HTML, Blade-представления и веб-страницы в изображения PNG, JPEG и PDF-файлы. По умолчанию пакет запускает и управляет Chrome непосредственно из PHP, без Node.js и Puppeteer. Результаты можно сохранять локально или размещать на любом настроенном диске файловой системы Laravel.
Создание снимков представлений и веб-страниц
Для передачи содержимого используются методы html(), view() и url(). Например, образовательная платформа может создавать изображения сертификатов об окончании курса, которыми пользователи смогут делиться. Следующий пример предполагает наличие Blade-представления certificates.show и модели $certificate.
use DirectoryTree\Screenshot\Facades\Screenshot;
Screenshot::view('certificates.show', data: ['certificate' => $certificate])
->size(width: 1440, height: 900)
->jpeg(quality: 85)
->store(path: "certificates/{$certificate->id}/preview.jpg", disk: 's3');По умолчанию создаются изображения PNG. Для смены формата используются методы jpeg() и pdf(). Одного изменения расширения файла недостаточно.
JavaScript по умолчанию отключен. Если требуется сделать снимок общедоступной страницы продукта, использующей JavaScript, его можно включить с помощью метода javascript().
В следующем примере $product->public_url содержит полный HTTP- или HTTPS-адрес страницы.
use DirectoryTree\Screenshot\Facades\Screenshot;
Screenshot::url($product->public_url)
->javascript()
->size(width: 1280, height: 720)
->png()
->viewport()
->save(storage_path("app/product-{$product->id}-page.png"));Screenshot ожидает события load страницы. Если данные загружаются или графики отрисовываются после этого события, снимок может быть создан до завершения этих операций. Для HTML и Blade-представлений следует использовать абсолютные URL ресурсов или тег <base href="...">, чтобы Chrome мог загружать таблицы стилей и изображения.
Метод size() задает размер области просмотра Chrome, используемой при отображении страницы. По умолчанию изображения охватывают всю страницу, но их максимальная ширина ограничена 2048 пикселями, а высота составляет не более 10 000 пикселей. Вызов viewport(), показанный в предыдущем примере, ограничивает снимок видимой областью просмотра в пределах этих значений.
Снимки отдельных элементов и создание PDF
Метод element() позволяет выбрать элемент страницы с помощью CSS-селектора. Его необходимо вызвать до выбора выходного формата. Например, если страница сертификата содержит навигацию и кнопки скачивания, можно поместить сам сертификат в элемент #certificate и экспортировать только его.
use DirectoryTree\Screenshot\Enums\PaperSize;
use DirectoryTree\Screenshot\Facades\Screenshot;
$source = Screenshot::view('certificates.show', ['certificate' => $certificate])
->size(1440, 900)
->element('#certificate');
$source->png()->store(
path: "certificates/{$certificate->id}/certificate.png",
disk: 's3'
);
$source->pdf()
->paper(PaperSize::A4)
->landscape()
->store(
path: "certificates/{$certificate->id}/certificate.pdf",
disk: 's3'
);При создании изображения область кадрирования определяется границами выбранного элемента. При генерации PDF Chrome перемещает элемент в тело документа и печатает его с использованием таблиц стилей страницы. CSS-селекторы, зависящие от удаленных родительских элементов, могут потребовать корректировки.
По умолчанию PDF создаются в формате A4 в портретной ориентации, с полями по 10 мм и включенным отображением фоновых элементов. Размеры полотна и полей можно настраивать. Если в таблице стилей определен размер страницы через @page, метод preferCssPageSize() позволяет использовать именно его.
Сохранение и повторное использование снимков
Чтобы сохранить предварительный просмотр сертификата локально, а затем загрузить то же изображение в облачное хранилище, можно сохранить результат вызова capture().
use DirectoryTree\Screenshot\Facades\Screenshot;
$image = Screenshot::view('certificates.show', ['certificate' => $certificate])
->size(1440, 900)
->element('#certificate')
->png()
->capture();
$image->save(storage_path("app/certificate-{$certificate->id}.png"));
$image->store(
path: "certificates/{$certificate->id}/certificate.png",
disk: 's3',
options: ['visibility' => 'private'],
);Вызов save() или store() непосредственно у исходного объекта запускает новое создание снимка при каждом обращении. Объект, возвращаемый методом capture(), хранит уже полученные байты изображения, поэтому оба вызова в примере используют один и тот же результат.
Родительский каталог файла, передаваемого в save(), должен существовать заранее. Если при вызове store() не указывать disk, будет использоваться диск Laravel по умолчанию. Объекты изображений и PDF также предоставляют исходное содержимое, данные в формате Base64 и URI данных.
Установка
Screenshot поддерживает Laravel 12 с PHP 8.2 или новее, а также Laravel 13 с PHP 8.3 или новее.
Установка пакета выполняется через Composer:
composer require directorytree/screenshotЗатем необходимо выполнить команду установки:
php artisan screenshot:installПоставщик сервисов регистрируется автоматически. Если пакет еще не содержит установленной версии браузера, команда загружает Chrome for Testing. Для загрузки требуется расширение PHP ZIP. Проверить наличие более новой стабильной версии можно с помощью команды:
php artisan screenshot:install --updateЧтобы использовать уже установленный Chrome или Chromium, необходимо указать путь к исполняемому файлу через переменную окружения SCREENSHOT_CHROME_PATH. На сервере также должны быть установлены системные библиотеки, необходимые Chrome, и шрифты, используемые страницами.
Для удаленного рендеринга пакет поддерживает Gotenberg версии 8.38 и новее.
При локальном использовании Chrome именованные сокеты позволяют нескольким рабочим процессам совместно использовать браузер, если они запущены на одном хосте, от имени одного пользователя операционной системы и используют один закрытый каталог сокетов. При этом общий браузер означает и общие файлы cookie и хранилище данных.
В тестах метод Screenshot::fake() позволяет регистрировать создание снимков без запуска Chrome. При проверке загрузки файлов его можно использовать вместе с Storage::fake(). При этом поддельный объект Screenshot по-прежнему записывает файлы.
Дополнительные сведения о настройках, драйверах и примерах тестирования доступны в репозитории Screenshot на GitHub.