Display pdf file from local disk in Laravel 5? - php

I have a Laravel 5.5 app where users with administrator privileges can upload files. After they upload the files I'd like them to be able to view the file in the administrator dashboard.
I have a DocumentController.php that handles the file upload to the local disk:
public function store(Request $request)
{
// check to make sure user is an admin
$request->user()->authorizeRoles('admin');
// validate that the document is a pdf and
// that required fields are filled out
$this->validate($request, [
'title' => 'required',
'description' => 'required',
'user_id' => 'required|exists:users,id',
'document_path' => 'required|mimes:pdf'
]);
$file = $request->file('document_path');
$path = $file->store('documents/' . $request->user_id);
$document = Document::create([
'user_id' => $request->user_id,
'title' => $request->title,
'description' => $request->description,
'file_path' => $path
]);
return redirect($document->path());
}
This method takes the file from the form, makes sure it is a pdf and then saves the file to storage/app/documents/{user_id}. It then creates a Document record in the database and forwards to the URL based on the document id: /admin/document/{ $document->id }
That route is defined as Route::get('/admin/document/{document}', 'DocumentController#show');
Where in the controller I pass the document to the view:
public function show(Document $document, Request $request)
{
// check to make sure user is an admin
$request->user()->authorizeRoles('admin');
$storagePath = Storage::disk('local')->getDriver()->getAdapter()->getPathPrefix();
return view('admin.document', compact('document', 'storagePath'));
}
On that page I would like to display the pdf document.
resources/views/admin/document.blade.php
#extends('layouts.app')
#section('content')
<div class='container'>
<div class='row'>
<div class='col-sm-2'>
<a href='/admin'>< Back to admin</a>
</div>
<div class='col-sm-8'>
{{ $document }}
<embed src="{{ Storage::url($document->file_path) }}" style="width:600px; height:800px;" frameborder="0">
</div>
</div>
</div>
#endsection
I have tried using the $storagePath variable and Storage methods but cannot get the pdf file to display within the iframe.
Using local file storage how would I display the file in the browser? Also, I've protected the route so that only admins can view the document's page but what is the best way to secure the path to the document itself?

If you want your files to be protected (only admin can access them), then you need to create a new route and new DocumentController method getDocument
Add new route
Route::get('documents/pdf-document/{id}', 'DocumentController#getDocument');
In DocumentController, add
use Storage;
use Response;
Add new method that will read your pdf file from the storage and return it back
public function getDocument($id)
{
$document = Document::findOrFail($id);
$filePath = $document->file_path;
// file not found
if( ! Storage::exists($filePath) ) {
abort(404);
}
$pdfContent = Storage::get($filePath);
// for pdf, it will be 'application/pdf'
$type = Storage::mimeType($filePath);
$fileName = Storage::name($filePath);
return Response::make($pdfContent, 200, [
'Content-Type' => $type,
'Content-Disposition' => 'inline; filename="'.$fileName.'"'
]);
}
In your view you can show the document like this
<embed
src="{{ action('DocumentController#getDocument', ['id'=> $document->id]) }}"
style="width:600px; height:800px;"
frameborder="0"
>

Shorter version of that Response::make() from #ljubadr answer:
return Storage::response($document->file_path)

<embed
src="{{ url('/filepath') }}"
style="width:600px; height:800px;"
frameborder="0">

Related

How to make download feature (from other website link) in Laravel8?

Good evening, how to make a download feature (from another website link) in laravel 8?
for example I have a data link "download zip" from the github repository, then I want when I click download (in view) it will download from the github repo link.
actually it can be created in a view like <a href="$data->link">, but this method can't add the "download" value in the table.
I want to do this in the controller and when there is a download request it will also add value to the download field (table).
web.php
Route::get('source-code/download/{id}', [FrontController::class, 'download'])->name('download');
FrontController.php
public function download($id)
{
$sc = Sourcecode::findOrFail($id);
$sc->increment('download');
$sc->update();
if ($sc->file)
{
$file_path = public_path('storage/'.$sc->file);
return response()->download($file_path);
}
else
{
$headers = [
'Content-Type' => 'application/zip',
];
return response()->download($sc->link, 'testing.zip', $headers);
}
}
view
#if($sc->file || $sc->link)
<a href="{{ route('download', $sc->id) }}" target="_blank" rel="noopener" class="btn btn-primary btn-sm text-white">
Download
</a>
#endif
Currently, I can download from the folder, but from other website links, I still can't. how to make a feature like this? thank you
The method reponse()->download only seems to work on local files. If you want something similar for a remote file you can try the following:
public function download($id)
{
$sc = Sourcecode::findOrFail($id);
$sc->increment('download');
$sc->update();
if ($sc->file)
{
$file_path = public_path('storage/'.$sc->file);
return response()->download($file_path);
}
else
{
$data = file_get_contents($sc->link);
$headers = [
'Content-Type' => 'application/zip',
'Content-Disposition' => 'attachment; filename="testing.zip"',
'Content-Length' => strlen($data)
];
return response($data, 200, $headers);
}
}
Be aware that this will need to read the entire file in memory.
If the file is large then you can use a streamed download

How to display an storage image Laravel 5.2

I want tho disply an image on my view, but i receive: File not found.
The two errors:
FileNotFoundException in FilesystemAdapter.php line 61:
storage/app/public/covers/teste-bravo_cover.jpg
FileNotFoundException in Filesystem.php line 386: File not found at
path: storage/app/public/covers/teste-bravo_cover.jpg
But the image is in the correct folder:
Well, in Laravel 5.2 storage:link won't work.
Image store on disk -works fine to store the image
if($cover){
dump("ok1");
Storage::disk('public_covers')->put($covername, File::get($cover));
$coverObject = New Cover();
//path com o nome do arquivo
$coverObject->imagePath = 'storage/app/public/covers/'.$covername;
dump($coverObject->imagePath);
}
//Salva a capa com o path para o arquivo
$coverObject->save();
My filesystems (with the "public_covers" disk) -works fine to store the image
'public_covers' => [
'driver' => 'local',
'root' => storage_path('app/public/covers'),
'visibility' => 'public',
],
View code: (if movie have cover, show them)
#if($movie->cover)
<img src="{{route('cover.image', [$movie->cover])}}" />
#endif
Route code, directing to controller method
Route::get('/movieimage/{coverId}',
[
'as' => 'cover.image',
'uses' => 'MovieController#getimage'
]
);
Controller Method to take the image
public function getimage($coverId){
$movie = Cover::find($coverId);
//dump($movie);
$imagePath = $movie['imagePath'];
dump($imagePath);
$file = Storage::disk('public_covers')->get($imagePath);
$response = Response::make($file, 200);
return $response;
}
you can try
Need to include this
use Illuminate\Support\Facades\Storage;
And set in controller or route
Route::get('storage/{filename}', function ($filename)
{
$files = Storage::files('logs'); // set repo name of storage folder
$path = storage_path('public/' . $filename);
if (!File::exists($path)) {
abort(404);
}
$file = File::get($path);
$type = File::mimeType($path);
$response = Response::make($file, 200);
$response->header("Content-Type", $type);
return $response;
});
I am new to laravel. I had the same problem though am on laravel 5.8. I had created the symlink to display a pdf as a view but the FileNotFoundException persisted.
I ended up accessing the pdf using this url localhost:8000/storage/filename.ext.
After running ln -s /path/to/laravel/storage/public /path/to/laravel/public/storage or php artisan storage:link a storage folder is added to your appname/public directory. I think that once the link is created we access the images in the storage through the public link created. Try accessing the images via the new /appname/public/storage/app/pathtoimage folder created in the public directory and not pointing directly to the /appname/storage folder
<img src={{asset('/storage/pathtoimg')}} /> # using storage folder in public
Check this solution will work for you
How I solved my problem:
First of all, save the files on "public" folder.
On my filesystems.php i change my disk. Now my root are "public_path" and not "storage_path"
'public_covers' => [
'driver' => 'local',
'root' => public_path('images/covers'),
'visibility' => 'public',
],
My controller method
public function store(Request $request){
$cover = $request->file('cover');
$inputs = $this->request->all();
$this->validate($this->request, [
'title' => 'required|max:255',
'description' => 'required',
'gender' => 'required',
'secondGender' => 'required',
'year' => 'numeric|min:1900|max:2100',
'lenght' => 'numeric|min:10'
]);
//build movie model object
$movie = New Movie();
$movie->user_id = \Auth::user()->id;
$movie->gender_id = $inputs['gender'];
$movie->secondgender_id = $inputs['secondGender'];
$movie->title = $inputs['title'];
$movie->slug = str_slug($inputs['title']);
$movie->description = $inputs['description'];
$movie->lenght = $inputs['lenght'];
$movie->year = $inputs['year'];
//TODO Mudar a composição do nome da foto para impedir que no futuro se sobreponha uma capa com outro filme que venha a ter o mesmo nome
//TODO: Change the name createan to avoid overwrite the cover with an movie with the same name
$covername = str_slug($inputs['title']).'_cover' .'.jpg';
//if have an cover file
if($cover){
//storage the file on my public_covers (look my filesystems.php)
Storage::disk('public_covers')->put($covername, File::get($cover));
$coverObject = New Cover();
//path com o nome do arquivo
//path with the file name
$coverObject->imagePath = 'images/covers/'.$covername;
$coverObject->save();
$movie->cover_id = $coverObject->id;
}
$movie->save();
return redirect()
->route('user.dashboard')
->with([
'success' => 'Filme adicionado com sucesso!',
]);
}
My view image code
#if($movie->cover)
<img class="cover" src="{{ asset($movie->cover->imagePath) }}" alt="{{ $movie->title }}"">
#else
<img class="cover" src="{{ asset('images/noimage.jpg') }}" alt="{{ $movie->title }}">
#endif

Error. Failed to load pdf document in laravel

I want to load pdf file in html but i got an error.
here is my function
public function getDocument($file){
$filePath = 'app/final/attachments/AA-19-4-2019-18123/'.$file;
$type = Storage::mimeType($filePath);
$pdfContent = Storage::get($filePath);
return Response::make($pdfContent, 200, [
'Content-Type' => $type,
'Content-Disposition' => 'inline; filename="'.$file.'"'
]);
}
here is my route
Route::get('/documents/pdf-document/{file}', 'inboxController#getDocument');
and here is my code in blade
<embed src="{{ action('inboxController#getDocument', ['file'=> basename($attach)]) }}" style="width:100%;height:auto;overflow: hidden;" frameborder="0" allowfullscreen>
it seems like, the error is because of the filename of the file. When i changed it to asdf.pdf, it loaded the file, but when i change its filename i wont loaded anymore. Images doesnt have really a problem. only pdf files. Please help me
edit
when i tried to use this static code, then remove {file} from route and also in blade, then pdf will loaded. i cant figure it out why.
public function getDocument(){
$filePath = 'app/final/attachments/AA-19-4-2019-18123/my.pdf';
$type = Storage::mimeType($filePath);
$pdfContent = Storage::get($filePath);
return Response::make($pdfContent, 200, [
'Content-Type' => $type,
'Content-Disposition' => 'inline; filename="'.$file.'"'
]);
}
You can do it this way :
php artisan storage:link
Next Go to the storage folder under 'public', and create a Folder 'FOLDER_NAME'
Your function :
public function getDocument($filename){
return response()->file('storage/FOLDER_NAME/'.$filename);
}
In your routes, web.php :
Route::get('/pdf/{filename}', ['as' => 'filename', 'uses' => 'ControllerName#getDocument' ]);
Then you can call it from your blade :
See PDF File:

How to manipulate & resize images in laravel 5.5

I'm using The Public Disk which is local driver. I create a symbolic link from public/storage to storage/app/public using this given command php artisan storage:link. I didn't change anything as mentioned in laravel filesystem documentation. But i'm not able to view the image with asset helper. File_path is storing in database but still images are broken.
Controller:
public function store(Request $request)
{
$this->validate($request, [
'title' => 'required',
'file' => 'required|image|mimes:jpeg,png,jpg,gif,svg|max:2048',
]);
$slide = new Slider();
$slide->title = $request->title;
$slide->description = $request->description;
//uploading image
if ($request->hasFile('file')) {
$file = $request->file('file');
$slide->file_name = str_random(40) . $file->getClientOriginalName();
$slide->file_size = $file->getClientSize();
$slide->file_mime = $file->getClientMimeType();
$slide->file_path = $file->storeAs('public', $slide->file_name);
}
$slide->status = $request->status;
$slide->save();
return redirect()->route('slider.index')->with('success', 'Done');
}
I'm using storeAs method, which receives the path, the file name.
Database:
View:
<td><img src="{{ asset($slide->file_path) }}" class="content" width="25"></td>
StoreAs method returns the path which is public/filename.jpg and images store into public/storage folder. How do i view the images?
The public and S3 storages support the url method that you can use to get the correct URL for the image
<td><img src="{{ Storage::url($slide->file_path) }}" class="content" width="25"></td>
You should add storage prefix to your asset:
<td><img src="{{ asset('storage/' . $slide->file_path) }}" class="content" width="25"></td>

Laravel upload images to database

I'm trying upload image:
View (part):
<input type="file" name="image" />
Countoller:
public function store(Request $request){
dump($request->all());
$this->validate($request,[
'title'=>'required|max:255',
// 'image' => 'image|mimes:jpeg,png,jpg,gif,svg|max:2048',
'text'=>'required',
]);
$imageName = time().'.'.$request->image->getClientOriginalExtension();
$request->image->move(public_path('images'), $imageName);
dump($request);
$data=$request->all();
dump($data);
$aticle=new Article;
$aticle->fill($data);
}
Dump request:
"title" => "fgdfd"
"alias" => "dg"
"desc" => "fdgfgd"
"text" => "gd"
"image" => "IMG_0002.JPG"
"tag" => "hg"
How do I put an image in MySql database?
As the docs describe, you should be using the file() method on the $request to access the uploaded file, not the name of your file field.
In your case, that means:
// Use the file() method to access the uploaded file
$imageName = time() . '.' . $request->file('image')->getClientOriginalExtension();
// storeAs() allows you to move a file while specifying a new filename.
// $path will be the fully qualified path to the file, including filename.
$path = $request->file('image')->storeAs(public_path('images'), $imageName);
It isn't clear from your question whether you want to save the file path in the database, or the actual binary file contents, as a BLOB. Here's how to do both:
// Create new article
$aticle=new Article;
$aticle->fill($data);
// Either save the path to the uploaded image in the DB
$aticle->featured_image = $path;
$aticle->save();
// OR
// Save the file binary contents in the DB
$aticle->featured_image = file_get_contents($path);
$aticle->save();
Ideally, you'll save the file to a location and then store the path to that file in the database.
What version of Laravel are you on ? If you're on 5.3 or higher you can:
$path = $request->image->store('path/to/save/the/file');
this will save the file with a random name, then just store that path to the database.
or you can:
$path = $request->image->storeAs('path/to/save/the/file', 'filename.jpg');
if you want to specify the saved file name.
This work's for me:
Step 1
Use Intervention Image package for manipulating images. You'll install it via composer. Run the command:
composer require intervention/image
Step 2
After installing Intervention Image, you need to add service providers and facade. Open our config/app.php file and add following lines. In the $providers array add the service providers for this package.
Intervention\Image\ImageServiceProvider::class
Step 3
Add the facade of this package to the $aliases array.
'Image' => Intervention\Image\Facades\Image::class
Step 4
And finally publish the configuration using following command:
$ php artisan vendor:publish --provider="Intervention\Image\ImageServiceProviderLaravel5"
Step 5 Controller
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use DB;
use App\yourmodel;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Input;
use Response;
use Image;
class YourController extends Controller
{
public function create()
{
return view('yourview.create');
}
public function store(Request $request)
{
$file = Input::file('pic');
$img = Image::make($file);
Response::make($img->encode('jpeg'));
$var = new YourModel;
$var->pic = $img;
$var->save();
return redirect()->route('yourview.index')
->with('success','Success.');
}
Step 6 View
<form action="{{ route('yourview.store') }}" method="POST" enctype="multipart/form-data">
#csrf
<div class="row">
<div class="col-xs-4 col-sm-4 col-md-4">
<div class="form-group">
<strong>Image:</strong>
<input type="file" id="pic" name="pic" class="form-control"></input>
</div>
</div>
<div class="col-xs-12 col-sm-12 col-md-12 text-center">
<button type="submit" class="btn btn-primary">Send</button>
</div>
</div>
</form>

Categories