Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Knp Snappy Laravel Package

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.

View on GitHub
Deep Wiki
Context7
## Getting Started

### Minimal Setup
1. **Install the package** via Composer:
   ```bash
   composer require knplabs/knp-snappy
  1. Install wkhtmltopdf (required dependency):
    • Download from wkhtmltopdf.org (version 0.12.x).
    • Or install via Composer (for static binaries):
      composer require h4cc/wkhtmltopdf-amd64  # For 64-bit systems
      # or
      composer require h4cc/wkhtmltopdf-i386  # For 32-bit systems
      
  2. Initialize Snappy in your Laravel app:
    use Knp\Snappy\Pdf;
    
    $snappy = new Pdf('/path/to/wkhtmltopdf'); // Absolute path to binary
    

First Use Case: Generate a PDF from a URL

$snappy = new Pdf('/usr/local/bin/wkhtmltopdf');
header('Content-Type: application/pdf');
echo $snappy->getOutput('https://example.com');

First Use Case: Generate a PDF from HTML

$snappy->generateFromHtml('<h1>Hello</h1><p>World!</p>', storage_path('app/bill.pdf'));

Implementation Patterns

Common Workflows

1. PDF Generation from URLs

  • Single URL:
    $pdf = $snappy->getOutput('https://example.com');
    
  • Multiple URLs (Merged PDF):
    $pdf = $snappy->getOutput(['https://url1.com', 'https://url2.com']);
    

2. PDF Generation from HTML

  • Inline HTML:
    $snappy->generateFromHtml('<h1>Bill</h1>', storage_path('app/bill.pdf'));
    
  • HTML from a View:
    $html = view('pdf.invoice')->render();
    $snappy->generateFromHtml($html, storage_path('app/invoice.pdf'));
    

3. Image Generation (Snapshots)

use Knp\Snappy\Image;

$image = new Image('/usr/local/bin/wkhtmltoimage');
$image->getOutput('https://example.com')->saveToFile(storage_path('app/screenshot.png'));

4. Dynamic Options

  • Set Options Before Generation:
    $snappy->setOption('margin-top', '20mm');
    $snappy->setOption('margin-bottom', '20mm');
    $snappy->setOption('disable-smart-shrinking', true);
    $snappy->generateFromHtml($html, $filePath);
    
  • Reset Options:
    $snappy->resetOptions();
    

5. Handling Headers for Downloads

header('Content-Type: application/pdf');
header('Content-Disposition: attachment; filename="report.pdf"');
echo $snappy->getOutput('https://example.com');

Integration Tips

Laravel-Specific Patterns

  1. 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'));
    });
    
  2. Configuration: Store the wkhtmltopdf binary path in config/snappy.php:

    return [
        'binary' => env('WKHTMLTOPDF_BINARY', '/usr/local/bin/wkhtmltopdf'),
    ];
    
  3. 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);
        }
    }
    
  4. 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;
    }
    
  5. 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));
    

Gotchas and Tips

Common Pitfalls

  1. Binary Path Issues:

    • Gotcha: Passing arguments directly in the binary path (e.g., 'wkhtmltopdf --quiet') is deprecated and may fail.
    • Fix: Use setOption() instead:
      $snappy->setOption('quiet', true);
      
  2. Security Risks:

    • Gotcha: Enabling --enable-local-file-access can expose your system to attacks.
    • Fix: Avoid enabling it unless absolutely necessary. Sanitize all user input before processing.
  3. File Permissions:

    • Gotcha: wkhtmltopdf may fail if the binary lacks execute permissions.
    • Fix: Ensure the binary is executable:
      chmod +x /path/to/wkhtmltopdf
      
  4. Memory Limits:

    • Gotcha: Generating large PDFs may hit PHP's memory limit.
    • Fix: Increase memory_limit in php.ini or use ini_set():
      ini_set('memory_limit', '1024M');
      
  5. Cross-Platform Paths:

    • Gotcha: Windows paths (e.g., C:\path\to\wkhtmltopdf.exe) may cause issues.
    • Fix: Use forward slashes or the DIRECTORY_SEPARATOR constant:
      $snappy = new Pdf(str_replace('\\', '/', 'C:/path/to/wkhtmltopdf.exe'));
      
  6. Temporary Files:

    • Gotcha: Snappy creates temporary files during generation. Cleanup may fail if paths are invalid.
    • Fix: Ensure the temp directory is writable and use absolute paths.

Debugging Tips

  1. Check wkhtmltopdf Output: Enable logging to debug issues:

    $snappy->setOption('debug-javascript', true);
    $snappy->setOption('log-level', '9');
    
  2. Validate HTML/URLs:

    • Test URLs/HTML in a browser first to ensure they render correctly.
    • Use tools like HTML Tidy to validate HTML.
  3. Inspect Generated Commands: Use getCommand() to see the exact command being executed:

    $command = $snappy->getCommand('https://example.com', $outputFile);
    \Log::debug($command);
    
  4. 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.');
    }
    

Extension Points

  1. Custom Option Sets: Create reusable option configurations:

    $snappy->setOptions([
        'margin-top' => '10mm',
        'margin-bottom' => '10mm',
        'orientation' => 'Portrait',
    ]);
    
  2. 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());
    });
    
  3. 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;
        }
    }
    
  4. Queueable Jobs: Offload PDF generation to queues for better performance:

    class GeneratePdfJob implements ShouldQueue
    {
        use Dispatchable, InteractsWithQueue, Queueable;
    
        public $
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope