F
Filament3mo ago
Denxio

Private Image not showing

Form: FileUpload::make('image') ->image() ->disk('local') ->directory('post-images') ->visibility('private') ->placeholder('Upload an image') ->columnSpanFull() ->required(), Column: ImageColumn::make('image') ->disk('local') ->visibility('private'), Error: Still not viewable. Do I need to set up the other configuration files?
Solution:
Thanks, @Dennis Koch @awcodes . I realized that using the column foto in both the database as a column name and in the filesystems.php config file was causing the problem. I discovered when I noticed that setting up the label for "fotos" was ignored in the resource table: ```php...
Jump to solution
11 Replies
Dennis Koch
Dennis Koch3mo ago
So the disk is non public, right? Yes you need to set up a controller that serves those files and configure the temporaryUrl() for your disk.
Pathros
Pathros2mo ago
I also have the same problem in latest Filament v3 and Laravel v11. The ImageColumn() method is displaying the photo name, instead of the image itself. Here's my disk config at filesystems.php:
'photos' => [
'driver' => 'local',
'root' => storage_path('app/custom/staff/photos'),
'visibility' => 'private',//I also have tried with 'public' and doesn't work either
'url' => env('APP_URL').'/photos',
],
'photos' => [
'driver' => 'local',
'root' => storage_path('app/custom/staff/photos'),
'visibility' => 'private',//I also have tried with 'public' and doesn't work either
'url' => env('APP_URL').'/photos',
],
Here's the ImageColumn() method in the Resource:
public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\ImageColumn::make('foto')//as in the DB column name
->label('Fotografía')
->disk('photos')
,
public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\ImageColumn::make('foto')//as in the DB column name
->label('Fotografía')
->disk('photos')
,
That displays the picture file name, instead of the photo image itself. However, I can see the image right at the form:
Forms\Components\FileUpload::make('foto')// just like the db column name
->label('Fotografía')
->image()
->disk('photos')
->storeFileNamesIn('photos')
->openable()
->previewable()
->maxSize(2 * 1024)//2MB
->minFiles(0)
->maxFiles(1)
->placeholder('Imagen de perfil o avatar')
->columnSpanFull()
,
Forms\Components\FileUpload::make('foto')// just like the db column name
->label('Fotografía')
->image()
->disk('photos')
->storeFileNamesIn('photos')
->openable()
->previewable()
->maxSize(2 * 1024)//2MB
->minFiles(0)
->maxFiles(1)
->placeholder('Imagen de perfil o avatar')
->columnSpanFull()
,
What am I missing to make it display the image itself in the table, instead of the filename??? Any ideas?
awcodes
awcodes2mo ago
You need what Dennis recommended. Private files need to go through a proxy url that can sign them to make them accessible in a browser. The controller is where you would validate that the user has the right permissions to view the file.
Pathros
Pathros2mo ago
hello! I have tried 'public' in the filesystems.php config and have got the same result. =( Then, how to set that controller up?
awcodes
awcodes2mo ago
Your code isn’t actually setting anything to private. Did you run ‘php artisan storage:link’? Never mind I see it in your config. Yea with public you need to make sure to symlink the storage directory, with private you have to go through a controller. There should be plenty of tutorials on that on the web. It’s a laravel thing and not a filament thing. It could also be something as simple as the wrong url in the env or an asset_url in the env.
Pathros
Pathros2mo ago
What is strange is that I can see the image right in the form: However, in the table, I only see the name of the file, instead of the image itself: What I have tried is setting up a custom PhotoColumn.php:
<?php

namespace App\Tables\Columns\Sica\Academicos;

use Filament\Tables\Columns\Column;
use Filament\Tables\Columns\ImageColumn;
use Illuminate\Support\Facades\Storage;

class PhotoColumn extends Column
{
protected string $view = 'tables.columns.path.to.photo-column';
protected function getImageUrl(): ?string
{
$record = $this->getRecord();
$path = $this->getState();

if ($record && $path) {
return Storage::disk('fotos')->temporaryUrl($path, now()->addMinutes(5));
}

return null;
}
}
<?php

namespace App\Tables\Columns\Sica\Academicos;

use Filament\Tables\Columns\Column;
use Filament\Tables\Columns\ImageColumn;
use Illuminate\Support\Facades\Storage;

class PhotoColumn extends Column
{
protected string $view = 'tables.columns.path.to.photo-column';
protected function getImageUrl(): ?string
{
$record = $this->getRecord();
$path = $this->getState();

if ($record && $path) {
return Storage::disk('fotos')->temporaryUrl($path, now()->addMinutes(5));
}

return null;
}
}
that I use in the Resource table:
public static function table(Table $table): Table
{
return $table
->columns([
PhotoColumn::make('foto')
->label('Fotografía')
,
public static function table(Table $table): Table
{
return $table
->columns([
PhotoColumn::make('foto')
->label('Fotografía')
,
here's the view:
@props([
'state' => null,
])

@if ($state)
<img src="{{ $state }}" style="max-height: 100px;" alt="Image" />
@else
<span>No Image</span>
@endif
@props([
'state' => null,
])

@if ($state)
<img src="{{ $state }}" style="max-height: 100px;" alt="Image" />
@else
<span>No Image</span>
@endif
and I still see the exact same result: the image name, instead of the image itself. By the way, setting up a label doesn't work.
return $table
->columns([
Tables\Columns\ImageColumn::make('foto')
->label('Fotografía')
,
return $table
->columns([
Tables\Columns\ImageColumn::make('foto')
->label('Fotografía')
,
the label text "Fotografía" is not displayed, but "Foto" instead Any ideas how to fix this? How to make the images display?
Dennis Koch
Dennis Koch2mo ago
What does the outputted HTML look like? Makes no sense that your custom column doesn't work
Pathros
Pathros2mo ago
The HMTL of the table looks like the following:
<!--[if BLOCK]><![endif]--> <a
href="https://app.test/administracion-76f0soRlv4+pCDgFjA15X-IIS/personal-academico-administrativo/1"
class="flex w-full disabled:pointer-events-none justify-start text-start"
>
<div
class="fi-ta-text grid w-full gap-y-1 px-3 py-4"
>
<!--[if BLOCK]><![endif]--> <!--[if BLOCK]><![endif]--><!--[if ENDBLOCK]><![endif]-->

<div
class="flex "
>
<!--[if BLOCK]><![endif]-->
<div
class="flex max-w-max"
style=""
>
<!--[if BLOCK]><![endif]--> <div
class="fi-ta-text-item inline-flex items-center gap-1.5 "
>
<!--[if BLOCK]><![endif]--><!--[if ENDBLOCK]><![endif]-->

<span
class="fi-ta-text-item-label text-sm leading-6 text-gray-950 dark:text-white "
style=""
>
foto_perfil__academico__f__20240518_133235image-9.png
</span>

<!--[if BLOCK]><![endif]--><!--[if ENDBLOCK]><![endif]-->
</div>
<!--[if ENDBLOCK]><![endif]-->
</div>
<!--[if ENDBLOCK]><![endif]-->
<!--[if ENDBLOCK]><![endif]-->

<!--[if BLOCK]><![endif]--><!--[if ENDBLOCK]><![endif]-->
</div>

<!--[if BLOCK]><![endif]--><!--[if ENDBLOCK]><![endif]-->
<!--[if ENDBLOCK]><![endif]-->
</div>

</a>
<!--[if BLOCK]><![endif]--> <a
href="https://app.test/administracion-76f0soRlv4+pCDgFjA15X-IIS/personal-academico-administrativo/1"
class="flex w-full disabled:pointer-events-none justify-start text-start"
>
<div
class="fi-ta-text grid w-full gap-y-1 px-3 py-4"
>
<!--[if BLOCK]><![endif]--> <!--[if BLOCK]><![endif]--><!--[if ENDBLOCK]><![endif]-->

<div
class="flex "
>
<!--[if BLOCK]><![endif]-->
<div
class="flex max-w-max"
style=""
>
<!--[if BLOCK]><![endif]--> <div
class="fi-ta-text-item inline-flex items-center gap-1.5 "
>
<!--[if BLOCK]><![endif]--><!--[if ENDBLOCK]><![endif]-->

<span
class="fi-ta-text-item-label text-sm leading-6 text-gray-950 dark:text-white "
style=""
>
foto_perfil__academico__f__20240518_133235image-9.png
</span>

<!--[if BLOCK]><![endif]--><!--[if ENDBLOCK]><![endif]-->
</div>
<!--[if ENDBLOCK]><![endif]-->
</div>
<!--[if ENDBLOCK]><![endif]-->
<!--[if ENDBLOCK]><![endif]-->

<!--[if BLOCK]><![endif]--><!--[if ENDBLOCK]><![endif]-->
</div>

<!--[if BLOCK]><![endif]--><!--[if ENDBLOCK]><![endif]-->
<!--[if ENDBLOCK]><![endif]-->
</div>

</a>
Any ideas?
Dennis Koch
Dennis Koch2mo ago
Are you sure you are looking at the right code/the right table? That just doesn’t make sense.
Solution
Pathros
Pathros2mo ago
Thanks, @Dennis Koch @awcodes . I realized that using the column foto in both the database as a column name and in the filesystems.php config file was causing the problem. I discovered when I noticed that setting up the label for "fotos" was ignored in the resource table:
return $table
->columns([
Tables\Columns\ImageColumn::make('foto')
->disk('fotos')
->label('Fotografía') //IGNORED
,
return $table
->columns([
Tables\Columns\ImageColumn::make('foto')
->disk('fotos')
->label('Fotografía') //IGNORED
,
then I started changing the name to whatever and test the label()to see whether or not was ignored. So, finally it worked when I changed the word "foto" to something else:
Forms\Components\FileUpload::make('avatar')
->label('Fotografía')
->image()
->disk('avatares')
->storeFileNamesIn('avatares')

//....
return $table
->columns([
Tables\Columns\ImageColumn::make('avatar')
->disk('avatares')
->label('Fotografía') //no longer ignored
,
Forms\Components\FileUpload::make('avatar')
->label('Fotografía')
->image()
->disk('avatares')
->storeFileNamesIn('avatares')

//....
return $table
->columns([
Tables\Columns\ImageColumn::make('avatar')
->disk('avatares')
->label('Fotografía') //no longer ignored
,
and in filesystems.php
'avatares' => [
'driver' => 'local',
'root' => storage_path('app/path/to/avatares'),
'visibility' => 'private',
'url' => env('APP_URL').'/avatares',
],
'avatares' => [
'driver' => 'local',
'root' => storage_path('app/path/to/avatares'),
'visibility' => 'private',
'url' => env('APP_URL').'/avatares',
],
So, "private" visibility was not causing any problem. now it finally is working 🎉
Dennis Koch
Dennis Koch2mo ago
Glad you figured it out.