Display pdf file from local disk in Laravel 5?
Stefan Bogdanescu
Founder & Senior Architect · 2026-06-29
Displaying PDF Files from Local Disk in Laravel: A Secure Guide
As a senior developer working with the Laravel ecosystem, handling file uploads and secure access is a fundamental requirement. When you successfully save files to the local disk, the next challenge is securely making those files accessible to authorized users, especially when dealing with sensitive documents like PDFs.
The scenario you've described—allowing administrators to upload files and view them in a dashboard—is very common. While your initial setup using Storage::url() seems correct, file security and proper path management require careful attention to Laravel’s file system abstraction.
This post will walk you through the best practices for displaying PDF files from local storage in a Laravel application, focusing on security and robust implementation.
Understanding Local Storage and File Serving in Laravel
You are correctly utilizing the storage disk, which is the recommended way to store user-uploaded files in Laravel projects. When you use $file->store('documents/' . $user_id), Laravel saves the file inside the storage/app/documents/{user_id} directory. This path is abstracted away from the public web root for security purposes, meaning direct access outside of Laravel's routing system should be restricted.
The key to displaying this file lies in correctly utilizing Laravel’s Storage facade and ensuring that the URL generated points only to files that are authorized to be viewed.
Addressing the Display Issue: Using Storage::url() Correctly
You attempted to use {{ Storage::url($document->file_path) }}. If this method is not working as expected, it usually points to one of two issues: either the file path stored in the database isn't perfectly structured for the disk driver, or insufficient public access permissions are set up on the storage link itself.
The Recommended Method
For displaying files directly within a Blade view using HTML tags like <embed> or <iframe>, the Storage::url() helper is the most straightforward approach:
<embed src="{{ Storage::url($document->file_path) }}" style="width:600px; height:800px;" frameborder="0">
Why this works: The Storage::url() method generates a publicly accessible URL for the file stored on the configured disk (in your case, local). For this to work seamlessly, you must ensure that the route structure and authorization checks are handled correctly before this view is rendered.
Securing File Access: The Importance of Authorization
You rightly asked about securing the path. Never rely solely on the file path stored in the database for access control. The security layer must be enforced at the application routing level, not just by hiding a file on the disk.
Best Practice: Layered Security
- Route Protection: You have already done this correctly by protecting the route
/admin/document/{document}withauthorizeRoles('admin'). This ensures only admins can request the page. - Database Verification (Crucial Step): Before rendering the file, you must verify that the currently logged-in user actually owns or has permission to view that specific document record in the database.
In your show method, after fetching $document, you should add an explicit check:
public function show(Document $document, Request $request)
{
// 1. Ensure User is Admin (Authorization Check)
$request->user()->authorizeRoles('admin');
// 2. CRITICAL Security Check: Verify ownership/permission for the specific document ID
if (!$document->user_id || $document->user_id !== $request->user()->id) {
abort(403, 'Unauthorized action.');
}
// If checks pass, proceed to display the file.
$storagePath = Storage::disk('local')->path($document->file_path); // Use path() for direct disk access if needed
return view('admin.document', compact('document', 'storagePath'));
}
By verifying the relationship between the authenticated user and the document record before accessing any file system methods, you ensure that even if a malicious user guesses an ID, they cannot access files they do not own. This principle of least privilege is central to secure development practices, aligning with the robust architecture promoted by frameworks like Laravel.
Conclusion
Displaying local files in a Laravel application requires marrying file storage mechanisms with strict authorization logic. By leveraging the Storage facade for generating public URLs and critically implementing ownership checks within your controller methods, you can provide a secure, functional, and professional experience for your administrators. Always prioritize server-side validation and authorization above all else when dealing with user-uploaded content.