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:link
from 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.