Display image in a view Laravel 6 - php

I can't display my images in a tag img in my view. I can save my uploaded image in storage->app->public->books and save the image name in my database as well. But after I run php artisan storage:link to access my file in public->storage, but whatever if I user asset() or url() method, I can't display my images in img tag, just alt="" atribute, Someone knows what I'm doing wrong?
This is my Controller store().
public function store(Request $request)
{
// Handle File Upload
if($request->hasFile('book_image')){
// Get filename with the extension
$filenameWithExt = $request->file('book_image')->getClientOriginalName();
// Get just filename
$filename = pathinfo($filenameWithExt, PATHINFO_FILENAME);
// Get just ext
$extension = $request->file('book_image')->getClientOriginalExtension();
// Filename to store
$fileNameToStore= $filename.'_'.time().'.'.$extension;
// Upload Image
$path = $request->file('book_image')->storeAs('books', $fileNameToStore);
} else {
$fileNameToStore = 'noimage.png';
}
//save in database
$itens = \App\Book::create([
'book_name' => mb_strtolower($request->book_name),
'author_name' => mb_strtolower($request->author_name),
'publishing_name' => mb_strtolower($request->publishing_name),
'description' => $request->description,
'release_date' => $request->release_date,
'category' => mb_strtolower($request->category),
'book_image' => $fileNameToStore
]);
flash('Livro criado com sucesso !')->success();
return redirect()->route('admin.books.index');
}
And this is my html where I'm trying to display.
#foreach($books as $book)
<tr>
<td><input type="checkbox" class="checkthis" /></td>
<td>
<img style="width: 80px;height: 80px" src="{{ url('books/{$book->book_image}') }}" alt="{{$book->book_image}}">
</td>
<td>{{$book->book_name}}</td>
<td>{{$book->author_name}}</td>
<td>{{$book->publishing_name}}</td>
<td>{{$book->release_date}}</td>
<td>
</tr>
And my config->filesystems.php
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
],
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
],
's3' => [
'driver' => 's3',
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => env('AWS_DEFAULT_REGION'),
'bucket' => env('AWS_BUCKET'),
'url' => env('AWS_URL'),
'endpoint' => env('AWS_ENDPOINT'),
],
],

You need to pass src as below.
src="{{ url('books/'.$book->book_image) }}"
as storage folder
src="{{ asset('storage/books/'.$book->book_image) }}"

Related

How to avoid hard code in uploaded files path?

I'm creating logic about uploading avatars to users:
blade.php
<image src="{{ $user->profile->image ? storage_path() . '/ app/public/' . $user->profile->image : '' }}"/>
<input type="file" id="avatar" name="avatar" style="display:none;"/>
<label for="avatar">{{ __('text.select_file') }}</label>
Controller (update method):
public function update(User $user)
{
$this->authorize('update', $user->profile);
$data = request()->validate([
'name' => 'required',
]);
if (request('avatar')) {
$imagePath = request('avatar')->store('uploads/avatars', 'public');
$image = Image::make(storage_path("app/public/{$imagePath}"))->fit(800, 800);
$image->save();
$imageArray = ['image' => $imagePath];
}
auth()->user()->profile->update(array_merge(
$data,
$imageArray ?? []
));
return redirect("/profile/{$user->id}");
}
When I upload a picture it is stored in storage/app/public/uploads/avatars in DB value for avatar is uploads/avatars/name.jpeg
As you can see I have hard code app/public/ in controller and in view files, this is by default, I didn't change any paths, here is filesystem.php:
<?php
return [
'default' => env('FILESYSTEM_DRIVER', 'local'),
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
],
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
],
's3' => [
'driver' => 's3',
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => env('AWS_DEFAULT_REGION'),
'bucket' => env('AWS_BUCKET'),
'url' => env('AWS_URL'),
'endpoint' => env('AWS_ENDPOINT'),
'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false),
],
],
'links' => [
public_path('storage') => storage_path('app/public'),
],
];
So how do I avoid these coded paths? And why Laravel default store folder is in storage and not in public directory ? Should I upload avatars to public directory or to leave them in storage? I'm looking for best and correct practices ?
I'm not well versed in Laravel, but I think you should be storing everything publicly accessible in /public/ with public_path(): Difference between storing files in public directory and in storage in Laravel 5.4
Just calling public_path($user->profile->image) should work, but you'll probably want to keep some path in there to make sure the avatars are in their own directory. Perhaps you could write another helper function:
function avatar_path($filename){
return public_path('avatars/'.$filename);
}
Then use avatar_path() everywhere rather than storage_path()/public_path(). I'm not sure if something as straightforward as that is the "Laravel way" though.

Show this error "Undefined index: thumbnail" when add filesystem in laravel

When I add new public directory in Filesystem Disks in filesystems.php like below
'thumbnail' => [
'driver' => 'local',
'root' => storage_path('app/public/relativeContentPath/thumbnail'),
'url' => env('APP_URL').'/storage',
'visibility' => 'thumbnail',
'permissions' => [
'file' => [
'public' => 0664,
'private' => 0600,
],
'dir' => [
'public' => 0775,
'private' => 0700,
],
],
],
And in my Controller I want to save an image into thumbnail directory like below
$fileNameToStore = md5(time()).'.jpg';
$photoThumbnail = ImageResize::make($productContent)
->resize(80, 80, function ($constraint) { $constraint->aspectRatio(); } )
->encode('jpg',80);
Storage::disk('thumbnail')->put( $fileNameToStore, $photoThumbnail);
But it shows me the error Undefined index: thumbnail. I don't know why this error shows me. Any help appreciate
Change 'visibility' => 'thumbnail', to 'visibility' => 'public',
https://laravel.com/docs/8.x/filesystem#file-visibility
it can be public or private other then you can not set anything as per doc

Laravel File::delete not working

So I have a hidden input in my form where I set the name of old file
<input type="hidden" name="old_logo" value="{{ $company->logo }}">
And it is being set successfully:
<input type="hidden" name="old_logo" value="GsdRHGtbm950k6tegfuyjjDlnC3ABg4uQKB2mHrE.jpeg">
Then it goes to my controller:
public function update(Request $request, $id)
{
$company = Company::find($id);
$company->name = $request->input('name');
$company->address = $request->input('address');
// $company->logo = $request->input('logo');
if(null !== (($request->file('logo')))) {
File::delete('logo/' . $request->input('old_logo'));
$request->file('logo')->store('logo');
$company->logo = $request->file('logo')->hashName();
}
$company->save();
return redirect('admin/companies');
}
My file that I want to delete is stored in storage/app/public/logo/
Filesystems.php
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app/public'),
],
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
],
's3' => [
'driver' => 's3',
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => env('AWS_DEFAULT_REGION'),
'bucket' => env('AWS_BUCKET'),
],
],
];
It should be trying to delete from storage/app/public/logo/ ? As I tested $request->input('old_logo') is passed successfully as well. What I'm doing wrong? Can it be rights problem?
Ofcourse I wrote this: use File;
You need to pass the full path to the file. So, if the file is in public/logo directory, do this:
File::delete(public_path('logo/' . $request->old_logo));

Laravel - Need specific name of files and folders with storage function

i have a form with slug, input files, etc.
I need if i put por example in form:
slug = hello-how-are-you
file = header.png
file2 = home.png
Laravel create me a folder in storage like this: /projects/hello-how-are-you with the header.png and home.png.
I try it but can't do it.. i try with something like this:
public function storeProject(Request $request)
{
$project = new Project();
$project->slug = $request->input("slug");
$namefolder = $project->slug;
$project->position = $request->input("position");
$project->public = $request->input("public");
$header = $request->file('pathheader');
$home = $request->file('pathhome');
$project->pathheader = $header;
$project->pathhome = $home;
\Storage::disk('projects')->put('header.png', \File::get($header));
$project->save();
}
In filesystem i have this:
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
],
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
],
'projects' => [
'driver' => 'local',
'root' => storage_path() . '/projects',
],
's3' => [
'driver' => 's3',
'key' => env('AWS_KEY'),
'secret' => env('AWS_SECRET'),
'region' => env('AWS_REGION'),
'bucket' => env('AWS_BUCKET'),
],
],
SOLVED!
Thanks to #Dees040
If want smash the name of the file and do it without a foreach, you can do it like this:
public function storeProject(Request $request)
{
$project = new Project();
$project->slug = $request->input("slug");
$project->position = $request->input("position");
$project->public = $request->input("public");
$project->pathheader = $request->file('pathheader');
$project->pathhome = $request->file('pathhome');
\Storage::disk('projects')->makeDirectory($project->slug);
\Storage::disk('projects')->putFileAs($project->slug,$project->pathheader,'header.png');
\Storage::disk('projects')->putFileAs($project->slug,$project->pathhome,'home.png');
$project->save();
}
This might do the trick for you:
public function storeProject(Request $request)
{
$project = Project::create($request->only('slug', 'position', 'public', 'pathheader', 'pathhome'));
\Storage::disk('projects')->makeDirectory($project->slug);
foreach ($request->allFiles() as $file) {
\Storage::disk('projects')->putFileAs($project->slug, $file, $file->getClientOriginalName());
}
}
Create the directory first:
use Illuminate\Support\Facades\Storage;
Storage::disk('projects')->makeDirectory($namefolder);
And then, store the files:
$project->pathheader = Storage::disk('projects')->putFileAs($namefolder, $header, $header->getClientOriginalName());
$project->pathhome = Storage::disk('projects')->putFileAs($namefolder, $home, $home->getClientOriginalName());

Laravel Storage facade not returning good path

I'm trying to upload some files to a specific "disk" in Laravel and then to retrieve the URL from these files.
Here is my config/filesystem.php file:
'disks' => [
...
'thumbnails' => [
'driver' => 'local',
'root' => storage_path('app/public/pictures/thumbnails'),
'visibility' => 'public',
],
...
],
Here is the way I handle an uploaded file (very basic, just for testing purposes):
Route::post('upload', function(Request $request) {
$file = $request->file('file');
$path = $file->storeAs('/', 'myFile.'.$file->getClientOriginalExtension(), 'thumbnails');
return dd($path);
});
The file /storage/app/public/pictures/thumbnails/myFile.jpg is created, which is fine, but $path equals "myFile.jpg" instead of the full path. First strange thing.
Then if I use:
$url = Storage::disk('thumbnails')->url('myFile.jpg');
$url equals "/storage/myFile.jpg" instead of "/storage/app/public/pictures/thumbnails/myFile.jpg".
Am I missing something ?
By default the disk url method just prepends /storage as stated in the docs.
To customize the url add a url to your config:
'thumbnails' => [
'driver' => 'local',
'root' => storage_path('app/public/pictures/thumbnails'),
'visibility' => 'public',
'url' => 'the url',
],

Categories