You want to generate PDF files from HTML and CSS but don't want to limit yourself to some few CSS features that for example MPDF can process? Well, I'm happy to tell you that Chrome can do just that. π (And it works not only in PHP)
tl;dr
services:
# ...config of your application here...
pdfrenderer:
image: timoschwarzer/headless-pdf-renderer
security_opt:
- seccomp=./chromium.json
Drop the chromium.json
seccomp profile
next to your docker-compose.yml
. You should now be able to perform a
POST
request against http://pdfrenderer:8082/render
with html
set to
the HTML markup you want to render and get back a PDF file.
What you need
- Docker
- Your application that needs to render HTML to PDF
- Docker Compose (optional)
Starting the service
I made a simple API service that takes HTML and renders it to PDF using Chrome's print-to-PDF feature.
seccomp
profile
Grab the We need to enable some system features that are otherwise restricted for Chrome to be able to use the sandbox. (We don't want to run it without a sandboxβ¦)
To do that, we grab the according seccomp profile from here and put it in our project directory.
See Nicolas Portmann's article for more in-depth information about this.
Using standalone Docker
You can now start the service with the following docker command:
docker run \
--security-opt seccomp=./chromium.json \
-p 8082:8082 \
timoschwarzer/headless-pdf-renderer
Now make a POST
request against http://localhost:8082/render
with the
html
request field set to your HTML markup to render it to PDF.
Using Docker Compose
The usage with Docker Compose works similar to using standalone Docker. The only difference is that you can ditch the port forward and just use the service name as host, as it will be resolved by Docker automatically:
services:
# ...config of your application here...
pdfrenderer:
image: timoschwarzer/headless-pdf-renderer
security_opt:
- seccomp=./chromium.json
Send aPOST
request to http://pdfrenderer:8082/render
with the
html
request field set to your HTML markup.
Rendering HTML to PDF in Laravel
Once you have the service running, you can use Laravel's HTTP Client API to generate PDF files from HTML:
$response = Http::post('http://pdfrenderer:8082/render', [
'html' => view('invoice')->render(), // Render a Blade view
]);
$pdf = $response->body();
// Save the PDF file in storage...
Storage::put('pdfs', $pdf);
// ...or download it from a Controller
return response()->streamDownload(function () use (&$pdf) {
echo $pdf;
}, 'My PDF.pdf', [
'Content-Type' => 'application/pdf',
]);
Make sure you bundle all CSS inside your Blade template as the API currently does not support uploading multiple files.
See also
- Nicolas Portmann's article about running Chrome in Docker without disabling security features
- timoschwarzer/headless-pdf-renderer on GitHub