I am trying to use http://code.google.com/p/amazon-s3-php-class/ to force-dowload files from AWS S3. I have an mp3 that I want people to "play" or "download." By default the when you access the file directly on s3 it begins to play in the browser. I need to add an option to actually download. I have Googled and found came up with nothing. I conceptually know what needs to happen but don't know how to produce it php. I know I need to modify the headers to Content-Disposition: attachment. Any help would be greatly appreciated.
Thanks,
Michael
Amazon has now solved this problem and allows overriding of headers on a per-request basis with signed requests:
http://docs.amazonwebservices.com/AmazonS3/latest/API/index.html?RESTObjectGET.html
w00t!
The php scripts that have been mentioned so far will work ok, but the main downside is that every time a visitor on your site requests a file, your own servers will load it from the S3 and then relay that data to the browser. For low traffic sites, it's probably not a big deal, but for high traffic ones, you definitely want to avoid running everything through your own servers.
Luckily, there's a fairly straight-forward way to set your files to be forced to download from the S3. And you're exactly right - you just want to set the content-type and content-disposition (just setting content-disposition will work in some browsers, but setting both should work in all browsers).
This code is assuming that you're using the Amazon S3 PHP class from Undesigned:
<?php
// set S3 auth and get your bucket listing
// then loop through the bucket and copy each file over itself, replacing the "request headers":
S3::copyObject($bucketName, $filename, $bucketName, $filename, "public-read", array(), array("Content-Type" => "application/octet-stream", "Content-Disposition" => "attachment"));
?>
Now all your files will be forced to download. You may need to clear your cache to see the change. And obviously, don't do that on any file that you actually do want to be loaded "inline" in the browser.
The nice part with this solution is that applications that load media files directly (like let's say an mp3 player in Flash) don't care about the content-type or content-disposition, so you can still play your files in the browser and then link to download that same file. If the user already finished loading the file in flash, they'll most likely still have it in their cache, which means their download will be super quick and it won't even cost you any extra bandwidth charges from the S3.
Just add this to your file's metadata on s3:
Content-Disposition: attachment; filename=FILENAME.EXT
Content-Type: application/octet-stream
Just wanting to post a contribution to this, Alex Neth is correct on this reference, but i do not feel a link is sufficient information, using amazon's own AWS PHP SDK2. Below I've outlined a basic (untested) method for calling data this way, you can use either S3 Factory Method or AWS Service Builder to make the S3 Client.
<?php
// S3 Factory Method
/*use Aws\S3\S3Client;
$s3= S3Client::factory(array(
'key' => '<aws access key>',
'secret' => '<aws secret key>'
));*/
// OR AWS Service Builder
use Aws\Common\Aws;
// Create a service builder using a configuration file
$aws = Aws::factory('/path/to/my_config.json');
// Get the client from the builder by namespace
$s3 = $aws->get('S3');
// Now lets create our request object.
$command = $s3->getCommand('GetObject',array(
'Bucket' => 'your-bucket-name',
'Key' => 'keyname',
'ResponseContentType' => 'application/octet-stream',
'ResponseContentDisposition' => 'attachment; filename="filename.mp3',
));
$url = $command->createPresignedUrl('+1 days');
?>
You can then use PHP's header("Location: $url"); in order to redirect the visitor to the MP3 file with a force download, this should prevent it from playing in the browser, Please note, i use ResponseContentType quite frequently but I've never used ResponseContentDisposition with AWS (it should work according to the docs).
Converting this sample into a function should be easy, you could even pass in $bucket, $key, $force_download as such
<?php
use Aws\Common\Aws;
function gen_url($bucket,$key,$force_download=false){
// OR AWS Service Builder (personal method to do this)
// Create a service builder using a configuration file
$aws = Aws::factory('/path/to/my_config.json');
// Get the client from the builder by namespace
$s3 = $aws->get('S3');
$params = array(
'Bucket' => $bucket,
'Key' => 'keyname',
'ResponseContentType' => 'application/octet-stream',
'ResponseContentDisposition' => 'attachment; filename="filename.mp3',
);
if($force_download){
$params['ResponseContentType'] = 'application/octet-stream';
$params['ResponseContentDisposition'] = 'attachment; filename="'.basename($key).'"';
}
$command = $s3->getCommand('GetObject',$params);
return $command->createPresignedUrl('+1 days');
}
// Location redirection to an MP3 force downlaod
header("Location: ".gen_url("recordings","my-file.mp3",true));
// Location redirection to a MP3 that lets the browser decide what to do.
header("Location: ".gen_url("recordings","my-file.mp3"));
?>
WARNING, if you haven't figured it out, this requires the AWS PHP SDK 2 currently (April 7th 2014) found here http://aws.amazon.com/sdkforphp/ This code is mostly pseudo code and may require some additional tweaking to actually make work as i'm referencing this from memory.
So modify my example above to be like this
<?php
header('Content-Type: audio/mpeg');
header("Content-Disposition: attachment; filename={$_GET['file']};");
readfile("url to the file/{$_GET['file']}");
exit();
?>
Now you will want to put some validation in there so that you not giving the world access to every file you put on S3, but this should work.
If you are using a library like Tarzan AWS, you can add meta headers, that amazon will include when the file is retrieved. Check out the meta parameter in the update_object function here, for example:
http://tarzan-aws.com/docs/2.0/files/s3-class-php.html#AmazonS3.update_object
Also worth mentioning is you are able to hard-set the headers for files in S3. For example, if you need to force-download a certain file you can set the appropriate headers for that file. Such as defaulting to stream, and either having a secondary file set to force-download or spend the bandwidth to use php/fputs and force-download via PHP.
<?php
require_once __DIR__.'/vendor/autoload.php';
use Aws\Common\Aws;
function gen_url($bucket,$key,$force_download=false){
// OR AWS Service Builder (personal method to do this)
$config = array(
'key' => '',
'secret' => '',
);
// Create a service builder using a configuration file
$aws = Aws::factory($config);
// Get the client from the builder by namespace
$s3 = $aws->get('S3');
$params = array(
'Bucket' => $bucket,
'Key' => $key,
'ResponseContentType' => 'application/octet-stream',
'ResponseContentDisposition' => 'attachment; filename="'.$key,
);
if($force_download){
$params['ResponseContentType'] = 'application/octet-stream';
$params['ResponseContentDisposition'] = 'attachment; filename="'.basename($key).'"';
}
$command = $s3->getCommand('GetObject',$params);
return $command->createPresignedUrl('+1 days');
}
$bucket = '';
$filename = '';
$url = gen_url($bucket,$filename,true);
echo "\n".$url."\n\n";
The code above works, you just need to install the S3 composer dependency and link in the autoload file, put your key/secret into config and then supply the bucket/filename.
php would just download the file to the server, not the client. remember, php doesn't do anything on the client, it just returns content (html, javascript, css, xml, whatever...)
[edit: added for clarity]: php can serve audio content, but you want to serve a web page and audio at the same time. To get that client behaviour, you have to get the client to request the file based on the web page's html or javascript.
So you have to get the client to download the file. For instance, have an iframe on the page with the url of the file on s3. Use css to make the iframe invisible. It should render the page and download and play the mp3.
Otherwise, look into using javascript to kick of a download when the page loads. I'm not sure if that's possible.
This is now possible by overwriting the S3 headers using signed requests.
Request Parameters
There are times when you want to override certain response header values in a GET response. For example, you might override the Content-Disposition response header value in your GET request.
You can override values for a set of response headers using the query parameters listed in the following table.
response-content-type - Sets the Content-Type header of the response
response-content-disposition - Sets the Content-Disposition header of the response.
Note
You must sign the request, either using an Authorization header or a pre-signed URL, when using these parameters. They cannot be used with an unsigned (anonymous) request.
So, you would set those headers to:
response-content-disposition: attachment; filename=FILENAME.EXT
response-content-type: application/octet-stream
Found answer here: https://stackoverflow.com/a/5903710/922522
<?php
// PHP solution (for OP and others), works with public and private files
// Download url expires after 30 minutes (no experation after the download initiates, for large files)
// ***Forces client download***
$signed_url = $s3_client->getObjectUrl($s3_bucket_name, $s3_filename_key, '+30 minutes', array(
'ResponseContentType' => 'application/octet-stream',
'ResponseContentDisposition' => 'attachment; filename="your-file-name-here.mp4"'
));
redirect($signed_url);
I never tried Amazon's S3 hosting, but don't you have access to using .htaccess files there? Then you can set Content-Type and Content-Disposition for an entire directory with this entry:
<IfModule mod_headers.c>
<FilesMatch "\.(mp3)$">
ForceType audio/mpeg
Header set Content-Disposition attachment
</FilesMatch>
</IfModule>
Related
I am trying to download a file that I stored on S3 to my local Laravel installation to manipulate it. Would appreciate some help.
I have the config data set up correctly because I am able to upload it without any trouble. I am saving it in S3 with following pattern "user->id / media->id.mp3" --> note the fact that I am not just dumping files on S3, I am saving them in directories.
After successfully uploading the file to S3 I update the save path in my DB to show "user->id / media->id.mp3", not some long public url (is that wrong)?
When I later go back to try and download the file I am getting a FileNotFoundException at S3. I'm doing this.
$audio = Storage::disk('s3')->get($media->location);
The weird thing is that in the exception it shows the resource that it cannot fetch but when I place that same url in a browser it displays the file without any trouble at all. Why can't the file system get the file?
I have tried to do a "has" check before the "get" and the has check comes up false.
Do I need to save the full public URL in the database for this to work? I tried that and it didn't help. I feel like I am missing something very simple and it is making me crazy!!
Late answer but important for others,
$s3_file = Storage::disk('s3')->get(request()->file);
$s3 = Storage::disk('public');
$s3->put("./file_name.tif", $s3_file);
The response of $s3_file will be a stream, you can save that stream data to file using Laravel put file method, you will find this stream file in storage/public directory.
You can give your Content-Type as desired and Content-Disposition as 'attachment' because your files are coming from S3 and you have to download it as an attachment.
$event_data = $this->ticket->where('user_id', $user_id)->first();
$data = $event_data->pdf;
$get_ticket = 'tickets/'. $data;
$file_name = "YOUR_DESIRED_NAME.pdf";
$headers = [
'Content-Type' => 'application/pdf',
'Content-Disposition' => 'attachment; filename="'. $file_name .'"',
];
return \Response::make(Storage::disk('s3')->get($get_ticket), 200, $headers);
Say, you have AWS S3 as your default storage.
And you want to download my_file.txt from S3 to my_laravel_project\storage\app\my_file.txt
And you want to make it a one-liner
Storage::disk('local')->put('my_file.txt', Storage::get('my_file.txt'));
I have a website here http://www.voclr.it/acapellas/ my files are hosting on my Amazon S3 Account, but when a visitor goes to download an MP3 from my website it forces them to stream it but what I actually want it to do is download it to there desktop.
I have disabled S3 on the website for now, so the downloads are working fine. but really I want S3 to search the MP3s
Basically, you have to tell S3 to override the content-disposition header of the response. You can do that by appending the response-content-disposition query string parameter to the S3 file url and setting it to the desired content-disposition value. To force download try:
<url>&response-content-disposition="attachment; filename=somefilename"
You can find this in the S3 docs. For information on the values that the content-disposition header can assume you can look here.
As an additional information this also works with Google Cloud Storage.
require_once '../sdk-1.4.2.1/sdk.class.php';
// Instantiate the class
$s3 = new AmazonS3();
// Copy object over itself and modify headers
$response = $s3->copy_object(
array( // Source
'bucket' => 'your_bucket',
'filename' => 'Key/To/YourFile'
),
array( // Destination
'bucket' => 'your_bucket',
'filename' => 'Key/To/YourFile'
),
array( // Optional parameters
**'headers' => array(
'Content-Type' => 'application/octet-stream',
'Content-Disposition' => 'attachment'**
)
)
);
// Success?
var_dump($response->isOK());
Amazon AWS S3 to Force Download Mp3 File instead of Stream It
I created a solution for doing this via CloudFront functions (no php required since it all runs at AWS by linking to the .mp3 file on Cloudfront with a ?title=TitleGoesHere querystring to force a downloaded file with that filename). This is a fairly recent way of doing things (as of August 2022). I documented my function and how I set up my "S3 bucket behind a CloudFront Distribution" here: https://stackoverflow.com/a/73451456/19823883
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!
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.
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.
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');
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.
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 .'"'
]);
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.
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);
Retrieve File name first then in Blade file use anchor(a) tag like below shown. This would works for image view also.
view Pdf ;
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.
Retrieving Files
$contents = Storage::get('file.jpg');
Downloading Files
return Storage::download('file.jpg');
File URLs
$url = Storage::url('file.jpg');
You can try this, it will open a pdf or other asset as a tab in your browser:
Link to you doc
Using the anchor tag means it behaves link any other link.
The problem I have is that I need the Content-Disposition: attachment header to be present on EVERY file that hits my bucket.
In Wordpress, I can just use .htaccess to cover the filetypes in question (videos), but those rules do not extend to my S3 downloads which browsers are simply trying to open, instead of download.
I need an automated/default solution, since I am not the only one that uploads these files (our staff uploads through Wordpress, and the uploads all are stored on our S3 bucket). So using Cloudberry or other browsers is not useful for this situation. I can't adjust the files on a per-file basis (the uploads are too frequent).
Is there a way to do this?
(Other information: I'm using the "Amazon S3 and Cloudfront" plugin on Wordpress that is responsible for linking the two together. Unfortunately, the site is not public, so I cannot link to it.)
Unfortunately there is no way to set this for an entire bucket in S3, and also Cloudfront can only set Cache-Headers
But you can set The Content-disposition parameter when uploading files to S3.
For existing files, you must change the Header, so loop through every object in the Bucket, and copy it to itself using the new headers.
All I can say now, please post the code that uploads the file to S3.
First, you need to locate the code that puts the object in the bucket.
You can use notepad++ to search for "putObject" within the php files of whatever plugin you are using.
An example code from another WP plugin that stores files to S3 is as follows:
$this->s3->putObject( array(
'Bucket' => $bucket,
'Key' => $file['name'],
'SourceFile' => $file['file'],
) );
Now, simply add ContentDisposition' => 'attachment' like so:
$this->s3->putObject( array(
'Bucket' => $bucket,
'Key' => $file['name'],
'SourceFile' => $file['file'],
'ContentDisposition' => 'attachment',
) );
Thats it :)
Yes, you can set default Content-Disposition header for your each and every upcoming uploading file in your S3 bucket using Bucket Explorer's Bucket Default feature.
For existing files, you can use Update Metadata option that update metadata on every file exist in your bucket in batch.
You just need to -
Select Key as : Content-Disposition
Add Value as : attachment;filename={$file_name_without_path_$$}
Then update metadata on the files.
See this page to set Content-Disposition on your file.
More references:
http://www.bucketexplorer.com/documentation/amazon-s3--metadata-http-header-bucket-default-metadata.html
http://www.bucketexplorer.com/documentation/amazon-s3--how-to-manage-http-headers-for-amazon-s3-objects.html
http://www.bucketexplorer.com/documentation/amazon-s3--metadata-http-header-update-custom-metadata.html
Thanks
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!
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.
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.
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');
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.
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 .'"'
]);
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.
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);
Retrieve File name first then in Blade file use anchor(a) tag like below shown. This would works for image view also.
view Pdf ;
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.
Retrieving Files
$contents = Storage::get('file.jpg');
Downloading Files
return Storage::download('file.jpg');
File URLs
$url = Storage::url('file.jpg');
You can try this, it will open a pdf or other asset as a tab in your browser:
Link to you doc
Using the anchor tag means it behaves link any other link.