Thanks god the creation of screenshots is not a task that a developer need to execute frequently, however know how to create them can be beneficial for your development knowledge. In this case, to create a screenshot of a website in Symfony 3, we are going to use wkhtmltoimage and KnpSnappyBundle (a wrapper written in PHP for the wkhtmltoimage console commands).
wkhtmltopdf and wkhtmltoimage are open source command line tools to render HTML into PDF and various image formats using the Qt WebKit rendering engine, these run entirely "headless" and do not require a display or display service.
Requirements
You'll need wkhtmltoimage
available in your system and accesible in the command prompt. wkhtmltoimage is a command line tool to render HTML into PDF and various image formats using the Qt WebKit rendering engine. These run entirely "headless" and do not require a display or display service.
- Windows: you can download an installer for each architecture (x86 and x64) in the installation area. Although you can change the path of the wkhtmltoimage executable later in the config.yml file, is recommendable to have
wkhtmltoimage
accesible as an environment variable on your system (if you don't want to create an environment variable for wkhtmltopdf, then you can provide the entire path to the executable later). You can read how to create environment variables in windows in this article. - Debian/Ubuntu: You can install the distribution from wkhtmltopdf directly in the console using the following command :
$ sudo apt-get install wkhtmltopdf
Visit the homepage of wkhtmltopdf and wkhtmltoimage for more information here.
1) Installing and configuring SnappyBundle
Snappy by itself is a PHP (5.3+) wrapper for the wkhtmltopdf and wkhtmltoimage conversion utility. It allows you to generate either pdf or image files from html documents or websites, using the webkit engine. The KnpSnappyBundle provides a simple integration for your Symfony project.
To install SnappyBundle in your project, execute the following composer command :
composer require knplabs/knp-snappy-bundle
Or add manually adding the package name into your composer.json file and then execute composer install
:
{
"require": {
"knplabs/knp-snappy-bundle": "~1.4"
}
}
When the download is complete, enable the bundle adding the following line to your kernel :
$bundles = [
//..//
new Knp\Bundle\SnappyBundle\KnpSnappyBundle(),
];
Finally you just need to add the basic configuration in your config.yml
file providing and enabling the binary path of wkhtmltoimage.
Note that as mentioned previously, SnappyBundle requires wkhtmltoimage to work, therefore we need to provide in the binary option of the config.yml
the fullpath to the executable of wkhtmltoimage before using it, otherwise you'll face one of the most known errors :
Binary path in Windows
With the default installer (and default installation settings) of wkhtmltopdf, there should be a folder wkhtmltopdf/bin in the Program Files of your main partition with the executable of wkhtmltopdf (which includes wkhtmltoimage) inside, so you only need to provide the path of the following example.
However, if you used a custom installation, just change the path with the new one that contains the wkhtmltoimage executable in the binary
property.
# Windows configuration
knp_snappy:
image:
enabled: true
binary: "\"C:\\Program Files\\wkhtmltopdf\\bin\\wkhtmltoimage.exe\""
options: []
Binary path in Linux/Unix like
If you installed wkhtmltopdf using the apt-get method, the paths probably are :
# app/config/config.yml
knp_snappy:
image:
enabled: true
binary: /usr/local/bin/wkhtmltoimage
options: []
How to change screenshots generation settings
You can dinamically change settings by default in the config.yml
file :
# config.yml
knp_snappy:
image:
enabled: true
binary: "wkhtmltoimage"
options:
width: 1920
height: 1080
Or dinamically in your controller (or service etc) using PHP with the setOption method of snappy :
<?php
$snappyImage = $this->get('knp_snappy.image');
$snappyImage->setOption('height', 1080);
$snappyImage->setOption('width', 1920);
$snappyImage->setOption('quality', 100);
$snappyImage->setOption('disable-javascript', false);
//$snappyImage->setOption('crop-x', 0);
//$snappyImage->setOption('crop-y', 0);
2) Examples
Save screenshot from website in storage
By default, snappy provide you a way to generate images easily and the image will be saved in the path providen as second parameter of the generate method:
<?php
namespace sandboxBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
class DefaultController extends Controller
{
public function indexAction()
{
// Get snappy.image service
$imageGenerator = $this->get('knp_snappy.image');
$filepath = 'imagehd.jpg';//or filename.png
// Set dimensions of the output image
$imageGenerator->setOption('width',1920);
$imageGenerator->setOption('height',1080);
// Take a screenshot of Our Code World website !
$imageGenerator->generate('http://www.ourcodeworld.com', $filepath);
return new Response("Image succesfully created in ".$filepath);
}
}
Generate file download in a controller
To return an image as attachment, use a BinaryFileResponse with disposition as attachment:
<?php
namespace sandboxBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
class DefaultController extends Controller
{
public function indexAction()
{
// Get snappy.image service
$imageGenerator = $this->get('knp_snappy.image');
$filepath = 'imagehd.jpg';//or image.png
// Set dimensions of the output image
$imageGenerator->setOption('width',1920);
$imageGenerator->setOption('height',1080);
// Take a screenshot of Our Code World website !
$imageGenerator->generate('http://www.ourcodeworld.com', $filepath);
$response = new BinaryFileResponse($filepath);
$response->setContentDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT);
return $response;
}
}
Return image as response in a controller
To return an image as response, use a BinaryFileResponse with disposition inline:
<?php
namespace sandboxBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
class DefaultController extends Controller
{
public function indexAction()
{
// Get snappy.image service
$imageGenerator = $this->get('knp_snappy.image');
$filepath = 'imagehd.jpg';
// Set dimensions of the output image
$imageGenerator->setOption('width',1920);
$imageGenerator->setOption('height',1080);
// Take a screenshot of Our Code World website !
$imageGenerator->generate('http://www.ourcodeworld.com', $filepath);
$response = new BinaryFileResponse($filepath);
$response->setContentDisposition(ResponseHeaderBag::DISPOSITION_INLINE);
return $response;
}
}
Have fun !