Laravel DOMPDF: how to load image from storage folder?
Stefan Bogdanescu
Founder & Senior Architect · 2026-06-29
# Laravel DOMPDF: How to Load Images from Storage Folder Without Errors
Dealing with file access issues when generating PDFs using tools like DOMPDF can be frustrating. You have files sitting securely in your Laravel storage directory, yet the PDF renderer reports that the image is missing or of an unknown type. This often points to a mismatch between how the application serves files to the browser versus how an external library (like DOMPDF) accesses those resources.
As senior developers working within the Laravel ecosystem, understanding this interaction between file systems, routing, and PDF generation is crucial. Let's dive into why this happens and establish the most robust solution for loading images stored in `storage/app/` into your generated documents.
## The Root of the Problem: File Paths vs. Web Paths
The core issue stems from how DOMPDF attempts to resolve image paths. When you reference a path like `storage/app/v6_dashboard.png`, this is a local file system path. While it works perfectly fine in standard Blade views or web requests, PDF generation libraries often require resources to be accessible via a public HTTP URL.
Your initial attempts demonstrated this perfectly:
```html
```
The error "image not found or type unknown" confirms that the PDF generation process is looking for a publicly accessible resource, and the internal file system structure is not automatically mapped by the PDF renderer. Simply creating a route to serve the image (as you did) is a good step, but we need to ensure DOMPDF accesses *that* public URL correctly within its context.
## The Solution: Leveraging Laravel's Storage Facade for Public Access
The most professional and scalable way to handle assets in a Laravel application—whether they are served to the browser or an external renderer like DOMPDF—is by using the configured storage disks. This ensures that all file access follows established Laravel conventions, which aligns perfectly with best practices outlined by the Laravel team.
Instead of relying on custom routes for every image, we can use the `Storage` facade directly within our PDF generation logic to obtain the correct public URL for the asset.
### Step-by-Step Implementation
Here is how you should structure your code to ensure DOMPDF can successfully render the image:
**1. Ensure Storage Link is Public:**
Make sure your storage disk (e.g., `local`) is configured correctly in `config/filesystems.php`. For assets meant to be publicly accessible, they should generally reside in the `public` directory or be served via a route. Since you are using `storage/app`, we must explicitly generate a URL for it.
**2. Generate the Public URL:**
Inside your controller or PDF generation service, use Laravel's built-in methods to get the public path of the file before passing it to DOMPDF:
```php
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Response;
// Assuming you are in a method where you generate the PDF content
$imagePath = 'v6_dashboard.png'; // The filename stored in storage/app/
// 1. Get the path from the local disk
$path = Storage::disk('local')->path($imagePath);
// 2. Construct the public URL (this is what DOMPDF needs)
$imageUrl = Storage::disk('local')->url($imagePath);
// Now, use $imageUrl when constructing your HTML for DOMPDF
$htmlContent = "
";
```
**3. Handling Remote Content in DOMPDF:**
Since you noted setting `"DOMPDF_ENABLE_REMOTE" => true`, this tells DOMPDF to attempt loading external resources. By providing a properly formatted, publicly accessible URL (like the one generated by `Storage::url()`), you give DOMPDF exactly what it needs to fetch the image from the web server, resolving the "image not found" error.
## Conclusion: Consistency is Key
The fundamental incompatibility wasn't in the route itself, but in how the PDF generation library interacted with the file system structure. By shifting our focus from internal file paths (`storage/app/...`) to publicly accessible URLs generated by the Laravel Storage facade, we ensure consistency across web requests and PDF rendering. This approach keeps your application adhering to Laravel principles, making your code cleaner, more maintainable, and compatible with best practices when developing complex features like PDF generation. Always strive for URL-based access when dealing with external rendering tools!
```
The error "image not found or type unknown" confirms that the PDF generation process is looking for a publicly accessible resource, and the internal file system structure is not automatically mapped by the PDF renderer. Simply creating a route to serve the image (as you did) is a good step, but we need to ensure DOMPDF accesses *that* public URL correctly within its context.
## The Solution: Leveraging Laravel's Storage Facade for Public Access
The most professional and scalable way to handle assets in a Laravel application—whether they are served to the browser or an external renderer like DOMPDF—is by using the configured storage disks. This ensures that all file access follows established Laravel conventions, which aligns perfectly with best practices outlined by the Laravel team.
Instead of relying on custom routes for every image, we can use the `Storage` facade directly within our PDF generation logic to obtain the correct public URL for the asset.
### Step-by-Step Implementation
Here is how you should structure your code to ensure DOMPDF can successfully render the image:
**1. Ensure Storage Link is Public:**
Make sure your storage disk (e.g., `local`) is configured correctly in `config/filesystems.php`. For assets meant to be publicly accessible, they should generally reside in the `public` directory or be served via a route. Since you are using `storage/app`, we must explicitly generate a URL for it.
**2. Generate the Public URL:**
Inside your controller or PDF generation service, use Laravel's built-in methods to get the public path of the file before passing it to DOMPDF:
```php
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Response;
// Assuming you are in a method where you generate the PDF content
$imagePath = 'v6_dashboard.png'; // The filename stored in storage/app/
// 1. Get the path from the local disk
$path = Storage::disk('local')->path($imagePath);
// 2. Construct the public URL (this is what DOMPDF needs)
$imageUrl = Storage::disk('local')->url($imagePath);
// Now, use $imageUrl when constructing your HTML for DOMPDF
$htmlContent = "