File download not working in Laravel 5? - php

I have stored a file in /public/storage/attachment and the file has a hashname which is stored in my database as well in the attachments table filehashname column
public/attachment/N52lbwmzubAcgUfHYhCC4A6NFBniIVmK.pdf
In the view I'm displaying the file as a link so that when the user clicks the link the file gets downloaded.
<a href="{{ URL::to( '/download/'.$post->attachments[0]->filehashname) }}">
{{ $post->attachments[0]->filename }}
</a>
web.php
Route::get('/download/{filehashname}', 'PostController#downloadAttachment');
PostController
public function downloadAttachment($filehashname)
{
$file= public_path('/storage/attachment/'.$filehashname);
return response()->download($file, 'demo.pdf');
}
But this does not download the file it opens the URL http://localhost:8000/download/public/attachment/N52lbwmzubAcgUfHYhCC4A6NFBniIVmKfctqMNOq.pdf with Page Not Found
If I hardcode the filename and click the link then it downloads but dynamically passing the name of the file in url gives Page Not Found error.
How to solve this?

If your file is stored in public directory then try public_path() and if your file is saved in storage directory then try storage_path()
$destination = storage_path('storage/attachment/'); // if your storage folder contains only attachement folder then like this :- storage_path('attachment/');
or
$destination = public_path('storage/attachment/');
$pathToFile = $destination.$filehashname;
return response()->download($pathToFile,'demo.pdf');
Hope it helps :)

You just need to add downlaod option in anchor tag
<a href="{{ URL::to( '/download/'.$post->attachments[0]->filehashname) }}" download >
{{ $post->attachments[0]->filename }}
</a>
This is being answered here

Try this
$myFile = public_path($filehashname); # place file in public/ and check this;
# If works add this public_path("storage/attachment/".$filehashname);
$headers = ['Content-Type: application/pdf'];
$newName = "demo.pdf";
return response()->download($myFile, $newName, $headers);
public_path()

Related

Laravel 7.28 "the file does not exist error

i'm building a project with laravel 7.28. i list all of documents with foreach without a problem. then i listed and linked all of the documents like this
#foreach($customer->documents as $document)
<div class="col-md-2">
#if($document->extension == 'pdf')
<a href="{{ route('downloadDocument', $document->id) }}">
<img src="/assets/images/pdf_icon.png" alt="">
</a>
#endif
#if($document->extension == 'doc' || $document->extension == 'docx')
<a href="{{ route('downloadDocument', $document->id) }}">
<img src="/assets/images/docx_icon.png" alt="">
</a>
#endif
#if($document->extension == 'xlsx')
<a href="{{ route('downloadDocument', $document->id) }}">
<img src="/assets/images/xlsx_icon.png" alt="">
</a>
#endif
#if($document->extension == 'jpg' || $document->extension == 'jpeg'|| $document->extension == 'png'|| $document->extension == 'svg')
<a href="{{ route('downloadDocument', $document->id) }}">
<img src="/assets/images/photo1.png" alt="">
</a>
#endif
</div>
#endforeach
then i wrote route like this;
Route::get('downloadDocument/{id}', 'CustomerController#downloadDocument')->name('downloadDocument');
downloadDocument function is;
public function downloadDocument($id)
{
$path = '/assets/uploads/customers/';
$file = Upload::findOrFail($id);
$pathToFile = $path . $file->media;
return response()->download($pathToFile);
}
i'm sure that i have that file on database and on server or local. although i get error;
is there anyone to help me?
URL Path vs System Path
I believe you're confusing URL path from system path.
Browser see files with URL paths like this (http://foobar.com/assets/uploads/customers/xxx.png). When you print things to the template, the files are referenced in HTML as URL path. A path like /assets/uploads/customers/xxx.png is simply
URL with implicit domain.
From the server program perspective, the file is stored in your harddisk with system paths like:
C:\My Websites\foobar\public\assets\uploads\customers\xxx.png (Windows); or
/home/foobar/web/public/assets/uploads/customers/xxx.png (Linux or Macos).
So, although these paths look different, they might be referencing the same file. Just from different perspective.
How to correctly build $pathToFile?
The $pathToFile parameter of download needs to be the system path to the file. I don't believe the png file is at /assets/uploads/customers/xxx.png in your system (Putting an assets folder in system root / or C:\ is quite unusual).
If the assets/ folder is in your Laravel's public/ folder, you can rewrite your method with public_path() like this:
public function downloadDocument($id)
{
// Note: remove leading slash
$path = 'assets/uploads/customers/';
$file = Upload::findOrFail($id);
// Note: apply public_path() helper function
$pathToFile = public_path($path . $file->media);
return response()->download($pathToFile);
}
Documentation about public_path() in Laravel 7.x:
public_path()
The public_path function returns the fully qualified path to the public directory. You may also use the public_path function to generate a fully qualified path to a given file within the public directory:
$path = public_path();
$path = public_path('css/app.css');

Laravel 5.3 storage cant find uploaded file

I am using laravel Filesystem to store images, the image will be uploaded inside the default storage, example:
/home/user/Projects/mywebapp/storage/app/images/posts/1/e392e17926559e7cc4e7934f.png
I didnt change the config/filesystem.php and here is my controller method to upload an image,
public function storeImage( Request $request ) {
$image = $request->file( 'image' )->store( 'images/posts/'.Auth::user()->id );
echo Storage::url( $image ); // <- print the url of the uploaded image
}
This would print the image url like this,
http://localhost:8000/storage/images/posts/1/e392e17c6a8d7926559e8e7cc4e7934f.png
But the image file is not accessable from the browser!
I dont want to use php to dynamically fetch the images, i just wanted to make them publicly accessable over http. How to display the image?
you just have to make a change in config\filesystems.php form
'default' => local,
to 'default' => public,
then in console run php artisan storage:link
then try the above code and it will work
For me it worked when I added "../" to the url of the file:
#foreach($arquivos as $i)
<li class="list-group-item"> <img src="{{ asset('img/pdf.png') }}" /> {{ $i -> nome }} </li>
#endforeach
And I am saving the file like this:
$ext = $request->arquivo->extension();
$path = $request->arquivo->storeAs('/relatorios', $nameoffile. "." . $ext);

How to display image from aws s3 in blade laravel 5.2

I have created a method for getting the data(image file) from aws S3 like this :
public static function getImage ($imagePath)
{
if(Storage::exists($imagePath))
{
return Storage::disk('s3')->get($imagePath);
}else
{
return 'No Image';
}
}
I'm sure that those image is exist on the aws, so there is no problem with that.
And then I use above method as the src in my blade view like this :
{!!Html::image(getImage($myPath),'logo',['width'=>60,'height'=>55])!!}
$myPath here already point to the specific file on aws for example : bucket/file.jgp. But when I run my webpage, this Html::Image gives a view like this :
What's going on here ? Why Html::image can't render my image file ? :(
Works on Laravel 6.x
<img src="{{Storage::disk('s3')->url($imagePath)}}">
You can use Storage::url($imagePath). Please see Filesystem / Cloud storage on laravel docs
{!!Html::image(<Your S3 bucket URL>.$myPath),'logo',['width'=>60,'height'=>55])!!}
You can save the S3 URL in a config file and use the config value instead of writing actual value everytime.
I had the same issue. This code snippet solved it
<img src="{!! url(<path to your image>) !!}" />
First, you need to give it public promotion in the controller
$path = Storage::disk('s3')->put('profileImages/', $request->file('profile_image'), 'public');
//save image name in database
$user->profile_image = basename($path);
In blade file
<img src="{{Storage::disk('s3')->url('profileImages/' . $user->profile_image)}}" />
You can add an accessor like follow to get Image URL
It returns URL to the image and you can access it by $profile->image
public function getImageAttribute($value)
{
if ($value) {
return Storage::disk('s3')->url($value);
}
return "https://source.unsplash.com/96x96/daily";
}
I assume you save image as follow
$path = $request->file('image')->store('images', 's3');
Storage::disk('s3')->setVisibility($path, 'public');
$profile->update([
'image' => $path
]);
You can check this commit for more detail
https://github.com/itxshakil/ediary/commit/23cb4b1cb7b8a4eac68f534e8c5b6897abc6421a
I have read every solution and no one has pointed it directly. So I thought to write my answers. For this problem I just required to add this simple line and boom, it starts working. But I got access denied alert you should check that problem too.
<img class="img-responsive" src="{!! Storage::disk('s3')->url('thumbs/' . $business->image->path) !!}" alt="thumb">
This works
Storage::disk('s3')->url($imagePath)
and also from your Minio Browser.
You have to Add a policy to Read and Write
I think that private visibility of images is an important security feature.
I found a solution :-)
Method in Controller:
/**
* #param string $name : image name on bucket
* ( stored if you want into database )
*/
public function show( $name ) {
$path = config('filesystems.disks.s3.base_directory') . '/' . $name;
$type = pathinfo($path, PATHINFO_EXTENSION);
$data = Storage::get( $path );
$base64 = 'data:image/' . $type . ';base64,' . base64_encode( $data );
return view( 'show', [ 'src' => $base64 ]);
}
The view:
...
<div class="panel panel-primary">
<div class="panel-heading"><h2>Laravel File Retrive with Amazon S3 </h2></div>
<div class="panel-body">
**<img src="{{ $src }}"/>**
</div>
</div>
...

Laravel Response::download not working and pdf file not downloaded when clicked button

I'm trying to achieve a link in a menu bar, such that when a user clicks on the link, a pdf file will be downloaded automatically, and it should not navigate to other pages.
Inside my main.blade.php, consists of a menu bar, I have this link:
Help
where $_SERVER['SERVER_NAME'] is localhost.
Inside my routes.php:
Route::get('/download', array('uses'=>'MainController#getDownloadHelp'));
Inside my controller called MainController:
public function getDownloadHelp()
{
$file= public_path(). "/public/download";
$filename = 'help.pdf';
$headers = array(
'Content-Type' => 'application/pdf',
);
return Response::download($file, $filename, $headers);
}
The PDF file is stored under /public/download/help.pdf
The problem I'm facing right now is, when I clicked the 'Help' link on the menu bar, it redirects me to localhost/download which is not what I wanted. And also, the pdf is not downloaded.
I really need some help here! Where and what did I went wrong?
You can try to use {{ URL::to('/download') }} instead of $_SERVER['SERVER_NAME']...
or in your blade
echo link_to('download', $title, $attributes = array(), $secure = null);
it will write all the <a></a> thing
for the path in the controller maybe you can remove the public in the path of the file like this
public_path() . '/download/';

Download files in laravel using Response::download

In Laravel application I'm trying to achieve a button inside view that can allow user to download file without navigating to any other view or route
Now I have two issues:
(1) below function throwing
The file "/public/download/info.pdf" does not exist
(2) Download button should not navigate user to anywhere and rather just download files on a same view, My current settings, routing a view to '/download'
Here is how Im trying to achieve:
Button:
<i class="icon-download-alt"> </i> Download Brochure
Route :
Route::get('/download', 'HomeController#getDownload');
Controller :
public function getDownload(){
//PDF file is stored under project/public/download/info.pdf
$file="./download/info.pdf";
return Response::download($file);
}
Try this.
public function getDownload()
{
//PDF file is stored under project/public/download/info.pdf
$file= public_path(). "/download/info.pdf";
$headers = array(
'Content-Type: application/pdf',
);
return Response::download($file, 'filename.pdf', $headers);
}
"./download/info.pdf"will not work as you have to give full physical path.
Update 20/05/2016
Laravel 5, 5.1, 5.2 or 5.* users can use the following method instead of Response facade. However, my previous answer will work for both Laravel 4 or 5. (the $header array structure change to associative array =>- the colon after 'Content-Type' was deleted - if we don't do those changes then headers will be added in wrong way: the name of header wil be number started from 0,1,...)
$headers = [
'Content-Type' => 'application/pdf',
];
return response()->download($file, 'filename.pdf', $headers);
File downloads are super simple in Laravel 5.
As #Ashwani mentioned Laravel 5 allows file downloads with response()->download() to return file for download. We no longer need to mess with any headers. To return a file we simply:
return response()->download(public_path('file_path/from_public_dir.pdf'));
from within the controller.
Reusable Download Route/Controller
Now let's make a reusable file download route and controller so we can server up any file in our public/files directory.
Create the controller:
php artisan make:controller --plain DownloadsController
Create the route in app/Http/routes.php:
Route::get('/download/{file}', 'DownloadsController#download');
Make download method in app/Http/Controllers/DownloadsController:
class DownloadsController extends Controller
{
public function download($file_name) {
$file_path = public_path('files/'.$file_name);
return response()->download($file_path);
}
}
Now simply drops some files in the public/files directory and you can server them up by linking to /download/filename.ext:
File Name // update to your own "filename.ext"
If you pulled in Laravel Collective's Html package you can use the Html facade:
{!! Html::link('download/filename.ext', 'File Name') !!}
In the accepted answer, for Laravel 4 the headers array is constructed incorrectly. Use:
$headers = array(
'Content-Type' => 'application/pdf',
);
Quite a few of these solutions suggest referencing the public_path() of the Laravel application in order to locate the file. Sometimes you'll want to control access to the file or offer real-time monitoring of the file. In this case, you'll want to keep the directory private and limit access by a method in a controller class. The following method should help with this:
public function show(Request $request, File $file) {
// Perform validation/authentication/auditing logic on the request
// Fire off any events or notifiations (if applicable)
return response()->download(storage_path('app/' . $file->location));
}
There are other paths that you could use as well, described on
Laravel's helper functions documentation
While using laravel 5 use this code as you don`t need headers.
return response()->download($pathToFile); .
If you are using Fileentry you can use below function for downloading.
// download file
public function download($fileId){
$entry = Fileentry::where('file_id', '=', $fileId)->firstOrFail();
$pathToFile=storage_path()."/app/".$entry->filename;
return response()->download($pathToFile);
}
HTML href link click:
<a ="{{ route('download',$name->file) }}"> Download </a>
In controller:
public function download($file){
$file_path = public_path('uploads/cv/'.$file);
return response()->download( $file_path);
}
In route:
Route::get('/download/{file}','Controller#download')->name('download');
I think that you can use
$file= public_path(). "/download/info.pdf";
$headers = array(
'Content-Type: ' . mime_content_type( $file ),
);
With this you be sure that is a pdf.
// Try this to download any file. laravel 5.*
// you need to use facade "use Illuminate\Http\Response;"
public function getDownload()
{
//PDF file is stored under project/public/download/info.pdf
$file= public_path(). "/download/info.pdf";
return response()->download($file);
}
HTML link click
<a class="download" href="{{route('project.download',$post->id)}}">DOWNLOAD</a>
// Route
Route::group(['middleware'=>['auth']], function(){
Route::get('file-download/{id}', 'PostController#downloadproject')->name('project.download');
});
public function downloadproject($id) {
$book_cover = Post::where('id', $id)->firstOrFail();
$path = public_path(). '/storage/uploads/zip/'. $book_cover->zip;
return response()->download($path, $book_cover
->original_filename, ['Content-Type' => $book_cover->mime]);
}
This is html part
<a href="{{route('download',$details->report_id)}}" type="button" class="btn btn-primary download" data-report_id="{{$details->report_id}}" >Download</a>
This is Route :
Route::get('/download/{id}', 'users\UserController#getDownload')->name('download')->middleware('auth');
This is function :
public function getDownload(Request $request,$id)
{
$file= public_path(). "/pdf/"; //path of your directory
$headers = array(
'Content-Type: application/pdf',
);
return Response::download($file.$pdfName, 'filename.pdf', $headers);
}
you can use simply inside your controller:
return response()->download($filePath);
Happy coding :)
If you want to use the JavaScript download functionality then you can also do
<a onclick="window.open('info.pdf) class="btn btn-large pull-right"><i class="icon-download-alt"> </i> Download Brochure </a>
Also remember to paste the info.pdf file in your public directory of your project

Categories