knplabs/knp-snappy
Snappy is a PHP wrapper for wkhtmltopdf/wkhtmltoimage to generate PDFs, thumbnails, and snapshots from URLs or HTML. Supports Linux/macOS/Windows, configurable binaries and options, and integrates with Symfony and Laravel via community bundles.
## Getting Started
### Minimal Setup
1. **Install the package** via Composer:
```bash
composer require knplabs/knp-snappy
wkhtmltopdf (required dependency):
0.12.x).composer require h4cc/wkhtmltopdf-amd64 # For 64-bit systems
# or
composer require h4cc/wkhtmltopdf-i386 # For 32-bit systems
use Knp\Snappy\Pdf;
$snappy = new Pdf('/path/to/wkhtmltopdf'); // Absolute path to binary
$snappy = new Pdf('/usr/local/bin/wkhtmltopdf');
header('Content-Type: application/pdf');
echo $snappy->getOutput('https://example.com');
$snappy->generateFromHtml('<h1>Hello</h1><p>World!</p>', storage_path('app/bill.pdf'));
$pdf = $snappy->getOutput('https://example.com');
$pdf = $snappy->getOutput(['https://url1.com', 'https://url2.com']);
$snappy->generateFromHtml('<h1>Bill</h1>', storage_path('app/bill.pdf'));
$html = view('pdf.invoice')->render();
$snappy->generateFromHtml($html, storage_path('app/invoice.pdf'));
use Knp\Snappy\Image;
$image = new Image('/usr/local/bin/wkhtmltoimage');
$image->getOutput('https://example.com')->saveToFile(storage_path('app/screenshot.png'));
$snappy->setOption('margin-top', '20mm');
$snappy->setOption('margin-bottom', '20mm');
$snappy->setOption('disable-smart-shrinking', true);
$snappy->generateFromHtml($html, $filePath);
$snappy->resetOptions();
header('Content-Type: application/pdf');
header('Content-Disposition: attachment; filename="report.pdf"');
echo $snappy->getOutput('https://example.com');
Service Provider Binding:
Bind Knp\Snappy\Pdf in a service provider for dependency injection:
$this->app->singleton('snappy.pdf', function ($app) {
return new Pdf(config('snappy.binary'));
});
Configuration:
Store the wkhtmltopdf binary path in config/snappy.php:
return [
'binary' => env('WKHTMLTOPDF_BINARY', '/usr/local/bin/wkhtmltopdf'),
];
Queueing Long-Running Jobs: Use Laravel Queues for generating large PDFs:
use Knp\Snappy\Pdf;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
class GeneratePdfJob implements ShouldQueue
{
use Queueable;
public function handle(Pdf $snappy)
{
$snappy->generateFromHtml($this->html, $this->filePath);
}
}
Middleware for PDF Routes: Create middleware to handle PDF generation and headers:
public function handle($request, Closure $next)
{
$response = $next($request);
if ($response->headers->get('Content-Type') === 'application/pdf') {
$response->header('Content-Disposition', 'attachment; filename="document.pdf"');
}
return $response;
}
Storing Generated Files: Use Laravel's filesystem to store PDFs:
use Illuminate\Support\Facades\Storage;
$path = $snappy->generateFromHtml($html);
Storage::put('pdfs/invoice.pdf', file_get_contents($path));
Binary Path Issues:
'wkhtmltopdf --quiet') is deprecated and may fail.setOption() instead:
$snappy->setOption('quiet', true);
Security Risks:
--enable-local-file-access can expose your system to attacks.File Permissions:
wkhtmltopdf may fail if the binary lacks execute permissions.chmod +x /path/to/wkhtmltopdf
Memory Limits:
memory_limit in php.ini or use ini_set():
ini_set('memory_limit', '1024M');
Cross-Platform Paths:
C:\path\to\wkhtmltopdf.exe) may cause issues.DIRECTORY_SEPARATOR constant:
$snappy = new Pdf(str_replace('\\', '/', 'C:/path/to/wkhtmltopdf.exe'));
Temporary Files:
Check wkhtmltopdf Output:
Enable logging to debug issues:
$snappy->setOption('debug-javascript', true);
$snappy->setOption('log-level', '9');
Validate HTML/URLs:
Inspect Generated Commands:
Use getCommand() to see the exact command being executed:
$command = $snappy->getCommand('https://example.com', $outputFile);
\Log::debug($command);
Handle Exceptions: Wrap Snappy calls in try-catch blocks:
try {
$snappy->generateFromHtml($html, $filePath);
} catch (\Exception $e) {
\Log::error('PDF generation failed: ' . $e->getMessage());
abort(500, 'Failed to generate PDF.');
}
Custom Option Sets: Create reusable option configurations:
$snappy->setOptions([
'margin-top' => '10mm',
'margin-bottom' => '10mm',
'orientation' => 'Portrait',
]);
Event Listeners: Extend Snappy by listening to its events (e.g., pre-generation hooks):
$snappy->addListener('preGenerate', function ($event) {
\Log::info('Generating PDF for: ' . $event->getSource());
});
Wrapper Classes: Create a Laravel-specific wrapper for Snappy:
class LaravelSnappy
{
protected $snappy;
public function __construct(Pdf $snappy)
{
$this->snappy = $snappy;
}
public function generateInvoice($user, $html)
{
$filePath = storage_path("app/invoices/{$user->id}.pdf");
$this->snappy->generateFromHtml($html, $filePath);
return $filePath;
}
}
Queueable Jobs: Offload PDF generation to queues for better performance:
class GeneratePdfJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable;
public $
How can I help you explore Laravel packages today?