0

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:

enter image description here

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:

enter image description here Greetings,

Parsa

2
  • When your image is saved, do you see the file in your public folder? You're not storing inside /images/, so that won't work either. Have you made changes to your filesystem.php? If you did, please share the configuration. Commented Jan 12, 2021 at 3:37
  • It is saved in the public folder inside my storage. I have not made changes to my filesystem.php Commented Jan 12, 2021 at 20:48

5 Answers 5

1

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;
        }
Sign up to request clarification or add additional context in comments.

7 Comments

Hi man, this did not work for me. I also tried: <img src="{{ asset('img/upload/' . $assortment->image_path) }}"> but this did not help as well.
change Storge Folder CH mod 777 ?
one note, if you are using nginx then you need removing "location ~* \.(jpg|jpeg|png|gif|ico|css|js)$"
@PhúcHậuTrần I also believe it has to do with my upload code. Let me check out if it works I will keep you updated :)
Hi @PhúcHậuTrần. I tried the code. I ran the test I have to see if the code works and it does. However, the image is not retrieved. I am using nginx. What is it I need to remove?
|
1

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 }}" />

14 Comments

Hi. I tried your code but it does not work. When I try to do the dd() it returns the following back to me: Error: Class 'App\Http\Controllers\Storage' not found
@Parsa_237 You need to import use Illuminate\Support\Facades\Storage; at the top in the controller class file.
Ok. The dd() works now and returns the following: "/storage/images/tVr4gaKyl5BuLY4U3QRiISdtnQ2kkxRhOho776o2.jpeg". But no image is still retrieved.
Can you check if there's a symlinked storage folder visible in your public directory. Also try to clear the compiled views by running php artisan view:clear
In my public folder there is a storage folder. When I click on it however, it says the link storage is broken.
|
0

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.

4 Comments

If not - can you provide the output of Storage::url($assortment->image_path
You mean dd()? I did element inspect on the element and it showed this link: /storage//tmp/php0Izlpp
Is that using the above exact controller method? Is the database value being saved as /php0Izlpp? It shouldn't be with the above.
Yes that exact controller method is being used.
0

Try <img src="{{ url('storage/images/'.$assortment->image_path) }}"/>

1 Comment

Hi man! This did not work for me. Still no image returned.
0

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.

5 Comments

The simplified version for the controller does not work for me. When I run my test testUserCanUploadFile the test fails.
Which part of it isn't working for you? Do note that it's saving into /images directory rather than public root. Could be the reason your test failed.
It is not saved in my public folder at all. Neither in my /images directory. When I checked my web source code and checked my image element. It showed a temporary link where the file is saved. It should show a filename. This has to do with my store() controller I believe.
That's very strangle. I tested the above code before posting here. The store methods are from Laravel's anyway. Have you verified your PHP settings for post_max_size and upload_max_filesize? Also have you tried on a different environment?
I think that if it was due to the file size, I would get an error regarding that. It has to due with my store() method controller. I am positive about that. One of the answers also was about the controller. But the code provided with it did not work.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.