Home > Software engineering >  Browser doesn't show image from laravel storage
Browser doesn't show image from laravel storage

Time:10-13

I'm using Laravel 8 with Docker on Windows 10 through WSL2 and Sail. I created a CRUD to store some articles with images in my DB. I'm trying to show images from laravel storage, but they are not appearing in the browser. How can I fix this?

ArticleController.php

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        return view('admin.articles.create');
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $validatedData = $request->validate([
            'title' => 'required',
            'body' => 'required',
            'author' => 'required',
            'image' => 'nullable | image | max:1024'
        ]);

        $image = Storage::put('images', $request->image); 
        $validatedData['image'] = $image;

        Article::create($validatedData);

        return redirect()->route('admin.articles.index');
    }

I followed the Laravel 8 docs to storage my images using the public disk.

filesystem.php

<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Default Filesystem Disk
    |--------------------------------------------------------------------------
    |
    | Here you may specify the default filesystem disk that should be used
    | by the framework. The "local" disk, as well as a variety of cloud
    | based disks are available to your application. Just store away!
    |
    */

    'default' => env('FILESYSTEM_DRIVER', 'public'),

    /*
    |--------------------------------------------------------------------------
    | Filesystem Disks
    |--------------------------------------------------------------------------
    |
    | Here you may configure as many filesystem "disks" as you wish, and you
    | may even configure multiple disks of the same driver. Defaults have
    | been setup for each driver as an example of the required options.
    |
    | Supported Drivers: "local", "ftp", "sftp", "s3"
    |
    */

    '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),
        ],

    ],

    /*
    |--------------------------------------------------------------------------
    | Symbolic Links
    |--------------------------------------------------------------------------
    |
    | Here you may configure the symbolic links that will be created when the
    | `storage:link` Artisan command is executed. The array keys should be
    | the locations of the links and the values should be their targets.
    |
    */

    'links' => [
        public_path('storage') => storage_path('app/public'),
    ]
];

I also created the link with the command line sail artisan storage:link Everything work well, because I can see the image in the right path: storage/app/images/my_image as follow:

enter image description here enter image description here

I have a problem when I try to show my image in the laravel blade as follow:

<div class="flex justify-center flex-wrap">
            @foreach ($articles as $article)
            {{-- Articles --}}
            <div class="max-w-sm rounded overflow-hidden shadow-lg my-5 mx-2">
                <img class="w-full"  src="{{ asset( 'storage/' . $article->image) }}" alt="article_image">
                <div class="px-6 py-4">
                    <div class="font-bold text-xl mb-2">
                        {{ $article->title }}
                    </div>
                    <p class="text-gray-700 text-base overflow-hidden h-16">
                        {{ $article->body }}
                    </p>
                    <span class="inline-block bg-gray-200 rounded-full px-3 py-1 mt-3 text-sm font-semibold text-gray-700">
                        {{ $article->author }}
                    </span>
                </div>
            </div>
            @endforeach
        </div>

I think the problem is on the path because on the browser i can see that: <img class="w-full" src="http://localhost/storage/images/9D1GCN9XDEwRWq8zN2wiA6eBSazgg657f9uUs0Uj.png" alt="article_image"> and the image is not shown.

I tried everything, change the filesystem, change the path storage into the controller etc etc.. but I can't find a solution.

CodePudding user response:

I think you should put get()

$image = Storage::put('images', $request->image->get());

If you don't define the disk like:

Storage::disk('public')->put('images', $request->image->get());

it will be in default disk ("local"). And to retrieve maybe you can put like:

<img class="w-full" src="{{ Storage::url('storage/' . $article->image) }}" alt="article_image">

A better approach would be:

$path = "image_" . time() . '.' . $request->image->extension();
Storage::disk('public')->put($path, $request->image->get());
Article::create([...,
   'image'=>$path,
]);

Retrieve

<img class="w-full" src="{{ Storage::url($article->image) }}" alt="article_image">

CodePudding user response:

As the image path in the browser looks right, I think is a problem with the symbolic link to the public directory generated with sail artisan storage:link.

I had the same problem and solved it running php artisan storage:linkfrom inside the container.

To me, the solution was making the link directly inside the container, not through sail.

# Get inside the container. Replace "your-project-container" with the actual name.
docker exec -it your-project-container /bin/sh
# Change to user sail
su sail
# Run artisan storage:link
php artisan storage:link
# Exit twice to get out the container
exit
exit

Doing sail artisan storage:link creates a wrong link with a non existing /var/www/html path outside the container.

  • Related