This tutorial will provide you details steps on how to secure pdf files In Laravel and only allow access to the authenticated users to preview or download pdf files.
Are looking to protected your pdf files generated by user or may be provided by you for your registered users into your application and you do not want to give access to those pdf files publicly basically no access to unauthenticated users.
It is always best practice and extremely necessary step that you should secure your pdf files.
Read – Advance way to export HTML to PDF – wkhtmltopdf
I assume that you already have Laravel project up and running and have pdf to protect for so let’s get started and see how to add restrictions to the pdf files from public access.
Table of Contents
Store PDF files outside of Public Directory
You should always store all pdf files into /storage
folder in laravel framework or many some other protected location which is outside of public directory.
Never store private files into public folder.
Public folder should only use to store public assets like JS, CSS, Images or any other public resource.
Alright now whatever files you have in your project make sure to move all of them into /storage folder with your preferred directory name.
I have stored all my pdf file into /storage/app/pdfs location now let’s move on to the next step.
Create a Controller
Create new controller which is going to have our http logic for making pdf files secure
php artisan make:controller PDFController
Add Method to Access PDF Files for Preview
Add new function in PDFController
called show()
which we will use to write code to access pdf from the storage
folder and render to the browser.
/app/Http/Controllers/PDFController.php
public function view($id)
{
$file = storage_path('app/pdfs/') . $id . '.pdf';
if (file_exists($file)) {
$headers = [
'Content-Type' => 'application/pdf'
];
return response()->download($file, 'Test File', $headers, 'inline');
} else {
abort(404, 'File not found!');
}
}
Quick note on the above view function if you see here I am directly passing the $id
to the path of the file because I am going to pass file name as argument to the preview route.
However in your case you might probably have pdf file id as argument and path of the pdf file is stored in the database.
If that is the case then simply fetch the path of the pdf file and assigned to the $file
variable.
Protect Controller with Auth Middleware
Now this important step we are going to protect our controller so that only authenticated user should have access to the http logic.
Go ahead and open PDFController.php
and add new construct
function along with the auth middleware as showing below:
/app/Http/Controllers/PDFController.php
public function __construct()
{
$this->middleware('auth');
}
Here how your our PDFController should look like after adding both the methods:
/app/Http/Controllers/PDFController.php
<?php
namespace App\Http\Controllers;
class PDFController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
public function view($id)
{
$file = storage_path('app/pdfs/') . $id . '.pdf';
if (file_exists($file)) {
$headers = [
'Content-Type' => 'application/pdf'
];
return response()->download($file, 'Test File', $headers, 'inline');
} else {
abort(404, 'File not found!');
}
}
}
Add Route to Controller
We are almost there now all we need is the route to the view function from the PDFController
/routes/web.php
Route::get('/preview-pdf/{id}', 'PDFController@view');
That is enough we have done with pdf file protection now we can go ahead and test whatever we did to secure our pdf files in laravel.
Test PDF file Protection
Browse: /preview-pdf/test-pdf-file into the browser and replace test-pdf-file to your file name or may be the id of the name.
You should see that the pdf file is ready to preview and download if you are authenticated user.
If you have note login yet then you will get redirected to the login page.
It’s a great tutorial, really helpful. How can I display many PDF documents using Views? I have many documents that I would like users to “View” and “Download”
You can use html iframe for each pdf file along with the separate buttons pointed to correct routes action.
Thanks, for your quick response. I have like 30 PDF documents that users will View or Download, kindly help me on how to create the Views and Routes. So far I don’t have any Views to display the documents.
Thanks
Here is the solution you can follow –
Create a pagination which includes one item per page for pdf files.
And have iframe which access the get route from your application which will pointed to the similar method I have used here in step #3.
Next whatever buttons you want add you can add those on top of iframe.
I already have a blade view with some buttons to redirect users to different PDF documents. I don’t want to use pagination because when the user clicks on a button, let’s say “My Test PDF” the user will be able to view the PDF on the browser (without leaving their dashboard)
Then you are good just use the iframe instead of opening pdf in new browser window. in this way your users will not leave the dashboard.
I have like 30 PDF documents, that means I will have to create 30 views? Or how does it work?
You don’t have to create multiple views, just needs to change iframe url dynamically.
Thanks for your help, let me work on it.
Great! Thank you from Brazil!
Thanks !, excellent I will apply it for image too
Thanks for the tutorial, great! If I want to prevent the user from downloading, copy and paste the pdf content displayed, kindly advise on how to achieve that?