Home » Php » php – Laravel – display a PDF file in storage without forcing download?

php – Laravel – display a PDF file in storage without forcing download?

Posted by: admin April 23, 2020 Leave a comment

Questions:

I have a PDF file stored in app/storage/, and I want authenticated users to be able to view this file. I know that I can make them download it using

return Response::download($path, $filename, $headers);

but I was wondering if there is a way to make them view the file directly in the browser, for example when they are using Google Chrome with the built-in PDF viewer. Any help will be appreciated!

How to&Answers:

Update for 2017

As of Laravel 5.2 documented under Other response types you can now use the file helper to display a file in the user’s browser.

return response()->file($pathToFile);

return response()->file($pathToFile, $headers);

Source/thanks to below answer

Outdated answer from 2014

You just need to send the contents of the file to the browser and tell it the content type rather than tell the browser to download it.

$filename = 'test.pdf';
$path = storage_path($filename);

return Response::make(file_get_contents($path), 200, [
    'Content-Type' => 'application/pdf',
    'Content-Disposition' => 'inline; filename="'.$filename.'"'
]);

If you use Response::download it automatically sets the Content-Disposition to attachment which causes the browser to download it. See this question for the differences between Content-Disposition inline and attachment.

Edit: As per the request in the comments, I should point out that you’d need to use Response at the beginning of your file in order to use the Facade.

use Response;

Or the fully qualified namespace if Response isn’t aliased to Illuminate’s Response Facade.

Answer:

Since Laravel 5.2 you can use File Responses
Basically you can call it like this:

return response()->file($pathToFile);

and it will display files as PDF and images inline in the browser.

Answer:

In Laravel 5.5 you can just pass “inline” as the disposition parameter of the download function:

return response()->download('/path/to/file.pdf', 'example.pdf', [], 'inline');

Answer:

I am using Laravel 5.4 and response()->file('path/to/file.ext') to open e.g. a pdf in inline-mode in browsers. This works quite well, but when a user wants to save the file, the save-dialog suggests the last part of the url as filename.

I already tried adding a headers-array like mentioned in the Laravel-docs, but this doesn’t seem to override the header set by the file()-method:

return response()->file('path/to/file.ext', [
  'Content-Disposition' => 'inline; filename="'. $fileNameFromDb .'"'
]);

Answer:

Ben Swinburne’s answer is absolutely correct – he deserves the points! For me though the answer left be dangling a bit in Laravel 5.1 which made me research — and in 5.2 (which inspired this answer) there’s a a new way to do it quickly.

Note: This answer contains hints to support UTF-8 filenames, but it is recommended to take cross platform support into consideration !

In Laravel 5.2 you can now do this:

$pathToFile = '/documents/filename.pdf'; // or txt etc.

// when the file name (display name) is decided by the name in storage,
// remember to make sure your server can store your file name characters in the first place (!)
// then encode to respect RFC 6266 on output through content-disposition
$fileNameFromStorage = rawurlencode(basename($pathToFile));

// otherwise, if the file in storage has a hashed file name (recommended)
// and the display name comes from your DB and will tend to be UTF-8
// encode to respect RFC 6266 on output through content-disposition
$fileNameFromDatabase = rawurlencode('пожалуйста.pdf');

// Storage facade path is relative to the root directory
// Defined as "storage/app" in your configuration by default
// Remember to import Illuminate\Support\Facades\Storage
return response()->file(storage_path($pathToFile), [
    'Content-Disposition' => str_replace('%name', $fileNameFromDatabase, "inline; filename=\"%name\"; filename*=utf-8''%name"),
    'Content-Type'        => Storage::getMimeType($pathToFile), // e.g. 'application/pdf', 'text/plain' etc.
]);

And in Laravel 5.1 you can add above method response()->file() as a fallback through a Service Provider with a Response Macro in the boot method (make sure to register it using its namespace in config/app.php if you make it a class). Boot method content:

// Be aware that I excluded the Storage::exists() and / or try{}catch(){}
$factory->macro('file', function ($pathToFile, array $userHeaders = []) use ($factory) {

    // Storage facade path is relative to the root directory
    // Defined as "storage/app" in your configuration by default
    // Remember to import Illuminate\Support\Facades\Storage
    $storagePath         = str_ireplace('app/', '', $pathToFile); // 'app/' may change if different in your configuration
    $fileContents        = Storage::get($storagePath);
    $fileMimeType        = Storage::getMimeType($storagePath); // e.g. 'application/pdf', 'text/plain' etc.
    $fileNameFromStorage = basename($pathToFile); // strips the path and returns filename with extension

    $headers = array_merge([
        'Content-Disposition' => str_replace('%name', $fileNameFromStorage, "inline; filename=\"%name\"; filename*=utf-8''%name"),
        'Content-Length'      => strlen($fileContents), // mb_strlen() in some cases?
        'Content-Type'        => $fileMimeType,
    ], $userHeaders);

    return $factory->make($fileContents, 200, $headers);
});

Some of you don’t like Laravel Facades or Helper Methods but that choice is yours. This should give you pointers if Ben Swinburne’s answer doesn’t work for you.

Opinionated note: You shouldn’t store files in a DB. Nonetheless, this answer will only work if you remove the Storage facade parts, taking in the contents instead of the path as the first parameter as with the @BenSwinburne answer.

Answer:

As of laravel 5.5 if the file is stored on a remote storage

return Storage::response($path_to_file);

or if it’s locally stored you can also use

return response()->file($path_to_file);

I would recommend using the Storage facade.

Answer:

Ben Swinburne answer was so helpful.

The code below is for those who have their PDF file in database like me.

$pdf = DB::table('exportfiles')->select('pdf')->where('user_id', $user_id)->first();

return Response::make(base64_decode( $pdf->pdf), 200, [
    'Content-Type' => 'application/pdf',
    'Content-Disposition' => 'inline; filename="'.$filename.'"',
]);

Where $pdf->pdf is the file column in database.

Answer:

Laravel 5.6.*

$name = 'file.jpg';

store on image or pdf

$file->storeAs('public/', $name );

download image or pdf

return response()->download($name);

view image or pdf

return response()->file($name);

Answer:

Retrieving Files
$contents = Storage::get('file.jpg');

Downloading Files
return Storage::download('file.jpg');

File URLs
$url = Storage::url('file.jpg');