Laravel showing image path from storage/app folder - php

I'm trying to display an image stored in my Storage folder but it showing a broken link icon.
Here's the controller
`public function getUserImage($filename)
{
$file = Storage::disk('public')->get($filename);
return new Response($file, 200);
}`
Here is the img src in my view
<img src="{{ route('account.image', ['filename' => $user->name . '-' . $user->id . '.jpg']) }}" alt="" class="img-responsive">
Here is my route code
Route::get('/user/{filename}',[
'uses' => 'UserController#getUserImage',
'as' => 'account.image'
]);

You should send a proper 'Content-Type' header for the response in case of sending images. The code may look like:
public function getUserImage($filename)
{
$response = Response::make(Storage::disk('public')->get($filename));
$response->header('Content-Type', 'image/png');
return response;
}

Related

Profile Image not displaying

I am currently doing an instagram clone project, and I have encountered a problem where the profile image is appearing broken. I have tried to echo out the path, and the problem is, despite this being the path specified:
/storage/app/public/profile/9UHe7CSRK4V9SNESMz0BAYggmQOp2G04J3Ygcgtl.png
The browser is returning this path
/storage/app/public/profile//9UHe7CSRK4V9SNESMz0BAYggmQOp2G04J3Ygcgtl.png
So you can see that the browser is adding a second '/' after profile, I don't know why.
Here is my index.blade
<div class="col-3 p-5">
<img src="{{ dd($user->profile->profileImage()) }}" class="rounded-circle w-100">
</div>
My Profile model
class Profile extends Model
{
protected $guarded = [];
public function profileImage()
{
$imagePath = ($this->image) ? $this->image : 'profile/9UHe7CSRK4V9SNESMz0BAYggmQOp2G04J3Ygcgtl.png';
return '/storage/app/' . $imagePath;
}
Profiles controller
class ProfilesController extends Controller
{
public function index(User $user)
{
return view('profiles.index', compact('user'));
}
public function edit(User $user)
{
$this->authorize('update', $user->profile);
return view('profiles.edit', compact('user'));
}
public function update(User $user)
{
$this->authorize('update', $user->profile);
$data = request()->validate([
'title' =>'required',
'description' =>'required',
'url' =>'url',
'image' =>'',
]);
if(request()->hasfile('image')){
$imagePath = request()->file('image')->store('profile', 'public');
$image = Image::make(public_path("storage/{$imagePath}"))->fit(1200, 1200);
$image->save();
}
auth()->user()->profile->update(array_merge(
$data,
['image' => $imagePath]
));
return redirect("/Profile/{$user->id}");
}
}
Routes
Route::get('/p/create', [App\Http\Controllers\PostsController::class, 'create'])->name('posts.create');
Route::get('/p/{post}', [App\Http\Controllers\PostsController::class, 'show']);
Route::post('/p', [App\Http\Controllers\PostsController::class, 'store']);
Route::get('/Profile/{user}', [App\Http\Controllers\ProfilesController::class, 'index'])->name('Profile.show');
Route::get('/Profile/{user}/edit', [App\Http\Controllers\ProfilesController::class, 'edit'])->name('profiles.edit');
Route::patch('/Profile/{user}', [App\Http\Controllers\ProfilesController::class, 'update'])->name('profiles.update');
Thanks in advance
You could load it into base64 with this PHP code:
$type = pathinfo(dd($user->profile->profileImage()), PATHINFO_EXTENSION);
$data = file_get_contents(dd($user->profile->profileImage()));
$imgbase64 = "data:image/" . $type . ";base64," . base64_encode($data);
then use
<img src="<?php echo $imgbase64; ?>" class="rounded-circle w-100">
This will then display the base64 image, which doesn't store the URL in plain text.

Retrieving image from database and showing it Laravel

I am making a web application in the Laravel Framework. I have written code that saves a image in the database.
Code for saving a image in the database (code in my controller):
public function store(Request $request)
{
$request->validate([
'title' => 'required',
'description' => 'required',
'category_id' => 'required',
]);
$user = request()->user();
$assortment = $user->assortments()->create($request->all());
if($request->hasFile('image') && $request->file('image')->isValid()) {
if($request->hasFile('image') && $request->file('image')->isValid()) {
//dd($request->image->store('images', 'public'));
$assortment->image_path = $request->image->store('images', 'public');
$assortment->save();
//Check what the Storage::url() generates
//dd(Storage::disk('public')->url($assortment->fresh()->image_path));
}
else {
abort(500, "Image not valid");
}
}
if ($request->wantsJson()) {
return response([], 204);
}
return redirect()->route('assortments.show', $assortment->slug)
->with('success','Verzameling is succesvol aangemaakt.');
}
I want my image to be retrieved from my database in the view but I do not know how to go about doing this. I tried things like:
<img src="/images/{{ $imageVariableName }}"> Variables and path are changed
The view I am trying to make my image be retrieved and shown:
<div class="mt-10">
<ul class="md:grid md:grid-cols-2 md:gap-x-8 md:gap-y-10">
#foreach ($assortment->itemCategories as $category)
<li>
<a href="{{ route('categories.show', [$assortment->slug, $category->id]) }}">
<div class="flex px-4 py-5 bg-white shadow overflow-hidden sm:rounded-md sm:px-6">
<div class="flex-shrink-0">
<div class="flex items-center justify-center h-12 w-12 rounded-md bg-indigo-500 text-white">
<!-- Heroicon name: globe-alt -->
</div>
</div>
<div class="ml-4">
<h4 class="text-lg leading-6 font-medium text-gray-900">{{ $category->name }}</h4>
</div>
</div>
</a>
</li>
#endforeach
</ul>
</div>
Anyone know how I go about doing this?
EDIT
I also tried:
<img src="{{ Storage::disk('public')->url($assortment->image_path) }}">
But it also returned no image. Just returned:
I inspected the image and it returned the following link:
http://localhost/storage/tmp/phpSX2W3G
EDIT
I know now the problem has to do with my upload controller. The file should not be stored at a temporary path: /storage//tmp/phpL1ZVcx
EDIT 2
The storage link appears to be broken. Get this in my public/storage:
Greetings,
Parsa
you can use
<img src={{Storage::url($assortment->img)}} />
EDIT:
I found out your problem, the problem not in the display but actually in your upload code
if ($request->hasFile('image')) {
$image = $request->file('image'); //request the file
$fileName = md5($image->getClientOriginalName() . microtime()) . '.' . $image->getClientOriginalExtension(); //use md5 for security reasons and get the extension.
$image->storeAs('', $fileName, 'public'); //store the file in the public folder disk.
$assortment->image_path = $fileName;
$assortment->save();
}
should become, because $filename just a temporary upload file it will be delete later, the actual upload path will be return by storeAs
if ($request->hasFile('image')) {
$image = $request->file('image'); //request the file
$fileName = md5($image->getClientOriginalName() . microtime()) . '.' . $image->getClientOriginalExtension(); //use md5 for security reasons and get the extension.
$assortment->image_path = $image->storeAs('', $fileName, 'public'); //store the file in the public folder disk.
$assortment->save();
}
EDIT2: if you are using nginx you need to remove these line
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 365d;
}
You can try the below:
Have included comments in the code with dd() statements to debug - uncomment the dd() statements if you don't get it working to check.
public function store(Request $request)
{
$validated = $request->validate([
'title' => 'required',
'description' => 'required',
'category_id' => 'required',
]);
$user = request()->user();
if(!$user) {
abort(401, 'Unauthenticated');
}
$assortment = $user->assortments()->create($validated);
if($request->hasFile('image') && $request->file('image')->isValid()) {
//dd($request->image->store('images', 'public'));
$assortment->image_path = $request->image->store('images', 'public');
$assortment->save();
//Check what the Storage::url() generates
//dd(Storage::disk('public')->url($assortment->fresh()->image_path));
} else {
abort(422, "Image not valid");
}
if ($request->wantsJson()) {
return response([], 204);
}
return redirect()->route('assortments.show', $assortment->slug)
->with('success','Verzameling is succesvol aangemaakt.');
}
Verify that you have a public disk configured in the config\filesystems.php, something like
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL') . '/storage',
'visibility' => 'public',
],
//And links specified for symlinking when php artisan storage:link is run
'links' => [
public_path('storage') => storage_path('app/public'),
],
Then run
php artisan storage:link
and check in the public folder that there exists a symlinked storage folder
Then in your blade view, you can use
<img src="{{ Storage::disk('public')->url($assortment->image_path) }}" />
//OR
<img src="/storage/{{ $assortment->image_path }}" />
Controller:
if ($request->hasFile('image')) {
$image = $request->file('image');
$assortment->image_path = $image->store('', 'public');
$assortment->save();
}
NB: Laravel by default will create a unique name for a file and manage extension for you - dependent on your use case you may not need to make this filename yourself.
Artisan Command
php artisan storage:link
Generates the correct symlinks for your public storage.
Template
{{ Storage::url($assortment->image_path) }}
Those three things together should work.
Try
<img src="{{ url('storage/images/'.$assortment->image_path) }}"/>
Try a much simplified version:
if ($request->hasFile('image')) {
$path = $request->file('image')->storePublicly('images'); // Store file in public disk & return path
$assortment->image_path = $path; // If you want filename only, use basename($path)
$assortment->save();
}
After that, you can use Storage::disk('public')->url($assortment->image_path) in your view. Using getClientOriginalExtension() and getClientOriginalExtension() probably isn't a good idea since it's not considered a safe value (source). Laravel's store method saves the file and returns the hashed filename with path for you so you don't have to worry about all that :)
Make sure storage symlink is created:
php artisan storage:link
Also make sure post_max_size and upload_max_filesize in your php.ini are set with sufficient amount.

I can't see my update profile image using laravel 6

i am trying to update the image of profil ,because to user at the beginning it creates account without image, after it goes the update, so i store the image in root /aswakfolder/public/storage/profiles and i insert image link in db profiles/nameimage.jpeg, i created a function in helpers.php file to display the image its work very will, the problem here is that I do not understand the helpers function, and it does not meet my needs, my need is when image upload and exists it displays my image if not it displays image not-found.jpeg,in my case it always displays not-found.jpeg.
stock image in my folder, and url image insert in db very well.
UsersController.php
public function update(Request $request, $id)
{
$user=User::find($id);
if($request->hasFile('image'))
{
$image = $request->file('image');
$path = $request->image->store('profiles');
$user->image = $path;
}
$request->image = $user->image;
$user->id = Auth::user()->id;
$user->update([
$user->name => $request->name,
$user->email => $request->email,
$user->telephone => $request->telephone,
$user->daten => $request->daten,
$user->country_id=> $request->country_id,
$user->state_id => $request->state_id,
$user->city_id => $request->city_id,
$user->image => $request->image,
]);
session()->flash('success', 'user updated successfully !!');
return redirect('users');
}
helpers.php
function productImage($path)
{
return $path && file_exists('/aswakfolder/public/storage/'.$path) ? asset('/aswakfolder/public/storage/'.$path) : asset('/aswakfolder/public/storage/not-found.jpg');
}
index.blade.php
<div class="inner" style="background-image: url({{ asset(productImage($users->image)) }})">
Make sure you run the commend php artisan storage:link to create the shortcurt on public/ folder.
Documentation

Display image from storage in view

I have a form with multiple fields which stores information including an image upload. There is also an edit view:
Route::PUT('/link/{link}', function (Request $request, Link $link) {
$request->validate([
'name' => 'required|max:255',
'title' => 'required|max:255',
'cell' => 'required|max:255',
'tel' => 'required|max:255',
'email' => 'required|max:255',
'website' => 'required|url|max:255',
'location' => 'required|max:255',
'image' => 'required|image|mimes:jpeg,png,jpg,gif,svg|max:2048',
]);
$img = $request->file('image');
$newfilename = $request->name;
$img->move(public_path("/uploads"), $newfilename);
$link->update($request->all());
return redirect('/');
});
The initial submit and edit works fine along with changing the image file name and storing it in the uploads folder.
The path generated being:
public/uploads/exampleFileName.jpg
The problem here is when it comes to displaying the image in the home view. The code below generates a 404 not found with an additional /tmp/ path which I have no idea about where it comes from.
Code in home view:
#foreach ($links as $link)
<div class="link-box">
<h5 class="off-white-txt">Card [# {{ $link->id }}]</h5>
<h5 class="off-white-txt"><span class="pool-blue-txt">Name: </span>{{ $link->name }}</h5>
<h5 class="off-white-txt"><span class="pool-blue-txt">Title: </span>{{ $link->title }}</h5>
<h5 class="off-white-txt"><span class="pool-blue-txt">Cell: </span>{{ $link->cell }}</h5>
<h5 class="off-white-txt"><span class="pool-blue-txt">Tel: </span>{{ $link->tel }}</h5>
<h5 class="off-white-txt"><span class="pool-blue-txt">Email: </span>{{ $link->email }}</h5>
<h5 class="off-white-txt"><span class="pool-blue-txt">Website: </span>{{ $link->website }}</h5>
<h5 class="off-white-txt"><span class="pool-blue-txt">Location: </span>{{ $link->location }}</h5>
<img src="{{url('uploads'.$link->image) }}" class="off-white-txt">
</div>
The error message in the console:
GET http://192.168.10.10/uploads/tmp/phpdtnTcw 404 (Not Found)
My question is the following; How could I edit my code to point to the correct path and display the image?
Thank you in advance.
if you are using storage folder to save images then you should use Storage::url
make sure to run command php artisan storage:link
<img src="{{ Storage::url($link->image) }}" class="off-white-txt">
The temporary path you are getting is from the image itself.
Why? Because you are not setting the image new path after moving the image, so the image is stored inside a temp storage.
To simplify it, you have indeed saved the image under public folder, but the image path is still in the temp storage. This is where the image resides. This temp storage is the default path for every UploadedFile object
You need to explicitly set it's path on the Link object, like so:
$link->image = 'my new path';
$link->save();
I think it is because you cannot access the uploads folder from the view.
I would suggest to create a controller that will get your image in the uploads folder and send a image Response. Something like this :
public function showImage($image)
{
if (!Storage::exists($image->name)) {
return false;
}
$file = Storage::get($image->name);
$type = Storage::mimeType($image->name);
$response = Response::make($file, 200)->header("Content-Type", $type);
return $response;
}
Then you just have to call the right route that points to your controller method :
<img src="{{ route('getMyImage', $image) }}" />
This way you can protect easily the files in your uploads folder (for exemple : put middleware or user control functions ...). Otherwise you can do the php artisan storage:link command
These are all valid points although the setup of my framework didn't play well with the suggestions. I have implemented a workaround for now.
This is the updated code in the web controller:
Route::post('/submit', function (Request $request) {
$data = $request->validate([
'name' => 'required|max:255',
'title' => 'required|max:255',
'cell' => 'required|max:255',
'tel' => 'required|max:255',
'email' => 'required|max:255',
'website' => 'required|url|max:255',
'location' => 'required|max:255',
'image' => 'required|image|mimes:jpeg,png,jpg,gif,svg|max:2048',
]);
$img = $request->file('image');
// Storage::disk('public')->put('uploads', $img);
$newfilename = $request->name;
$img->move(public_path("/uploads"), $newfilename);
$link = tap(new App\Link($data))->save();
return redirect('/');
});
This is the updated view code:
<img src="/uploads/{{ $link->name }}" class="user-img">
Thank you very much for all the help!

Laravel: cant get image from local /app

I can upload a image and see the image in storage/app/(abc.jpg)
and set the 'root' => storage_path('app'), in filesystems.php
account.blade.php
<img src="{{ route('account.image', ['filename' => $user->user_id . '.jpg']) }}" alt="" class="img-responsive">
routes.php
Route::get('/userimage/{filename}', [
'uses' => 'UserController#getUserImage',
'as' => 'account.image'
]);
Controller
public function getUserImage()
{
$file = Storage::disk('local')->get($filename);
return new Response($file, 200);
}
GET
http://localhost:8000/userimage/00bea23ff9dd07e5b175c0f8a9283ca8.jpg
500 (Internal Server Error)
In your controller method you need to define $filename like this...
public function getUserImage($filename)

Categories