salva/pdfjs-bundle
Salva PDF.js Bundle integrates Mozilla PDF.js into Symfony applications, providing Twig helpers, configurable viewer assets, and a simple way to embed browser-based PDF rendering without plugins or external services. Ideal for displaying PDF documents inline.
This is a Symfony2 bundle, not a Laravel package — there is no service provider, no facade, no config publish. As a Laravel developer, the realistic starting point is to treat the repository as a source of PDF.js viewer assets, not as an installable dependency.
composer require it into a Laravel app. The bundle targets Symfony 2.x and depends on the Symfony2 kernel/bundle system, which Laravel does not provide.Resources/public/ — the compiled PDF.js viewer (viewer.html, viewer.js, pdf.js, pdf.worker.js, cmaps/, images/).Resources/views/ — the Twig template that shows how the bundle embeds the viewer (typically an <iframe> pointing at viewer.html?file=...).SalvaPdfJsBundle.php / DependencyInjection/ — confirms there is no Laravel-relevant glue; skip these.public/vendor/pdfjs/ in your Laravel project. Preserve directory structure (the worker and cmaps must resolve relative to viewer.html).<iframe src="/vendor/pdfjs/web/viewer.html?file={{ urlencode($pdfUrl) }}">. That is the entire day-to-day pattern the bundle was providing, minus the Symfony wrapper.If your real goal is just "show a PDF in a Laravel app," skip this package entirely and use npm i pdfjs-dist (or a Blade wrapper around the CDN build). This bundle is a 2013-era snapshot; the upstream PDF.js has moved on substantially.
Asset extraction pattern (the only viable one here).
Treat the repo as a static asset bundle. Copy Resources/public/* into public/vendor/pdfjs/, then serve via an iframe or pdfjsLib in a Blade-injected script.
Streaming protected PDFs.
The viewer's ?file= parameter needs a URL the browser can fetch. For private documents, add a Laravel route that streams the file with proper headers:
Route::get('/documents/{document}/stream', function (Document $document) {
abort_unless(auth()->user()->can('view', $document), 403);
return response()->file(Storage::path($document->path), [
'Content-Type' => 'application/pdf',
'Accept-Ranges' => 'bytes',
]);
})->middleware(['auth']);
Then point the viewer at viewer.html?file=/documents/42/stream. Range support matters for the viewer's lazy loading; response()->file() handles it better than response()->download().
Blade component wrapper. Wrap the iframe so views stay readable:
{{-- resources/views/components/pdf-viewer.blade.php --}}
@props(['src', 'height' => '800px'])
<iframe
src="{{ asset('vendor/pdfjs/web/viewer.html') }}?file={{ urlencode($src) }}"
style="width:100%;height:{{ $height }};border:0"
title="PDF viewer"></iframe>
Configurable worker path.
If you go the pdfjs-dist route later, point the worker explicitly:
pdfjsLib.GlobalWorkerOptions.workerSrc = '/vendor/pdfjs/build/pdf.worker.min.js';
Migration path. If you find any actual Symfony service this bundle registers (it's minimal — mostly a Twig namespace), replicate it as a Laravel view namespace or a small helper class. Expect the total value to be one or two lines of Twig.
config/pdfjs.php, no artisan commands. Any Symfony-specific wiring in DependencyInjection/ is dead weight in Laravel.pdfjs-dist.viewer.html or serve it under a Blade route, the viewer will fail to load pdf.worker.js and cmaps/ — usually seen as "The PDF file is corrupted" or missing glyphs. Keep the whole web/ directory intact.?file= needs URL encoding. Blade's urlencode() or rawurlencode() for storage-backed or signed URLs; otherwise query strings on signed URLs break the viewer's fetch.Range requests. If you serve files through a controller, ensure your response allows ranges and does not strip Accept-Ranges. Signed S3 URLs work; a naive Response::make(file_get_contents(...)) does not.script-src, worker-src blob:, and frame-src allowances. The worker is loaded as a same-origin script, so keep it under your own domain.LICENSE and PDF.js header files when you vendor the assets. If you strip them, you're non-compliant.laravel.log. Test with the browser devtools network tab filtered to pdf.worker.js first.How can I help you explore Laravel packages today?