'Storing and displaying images with Laravel/Inertia/React privately

Currently have working on an image upload in a Laravel/Inertia/React stack.

Issue: It currently works using a symbolic link to the public folder. This is no good as it means anyone can access the images if they have the link. How can I do this differently so that only the owner of the image can view it?

Displaying the image:

<img src={`/storage/${props.company.logo_filename}`}/>

Storing the logo:


    public function storeLogo(Request $request)
    {
        $company = auth()->user()->company();


        $logo = $request->file('logo');
        $extension = $logo->getClientOriginalExtension();
        
        Storage::disk('public')->put($logo->getFilename() . '.' . $extension,  File::get($logo));

        dd(Storage::url('public/'. $logo->getFilename()));

        $company->logo_mime = $logo->getClientMimeType();
        $company->logo_original_filename = $logo->getClientOriginalName();
        $company->logo_filename = $logo->getFilename() . '.' . $extension;
        $company->save();

        //DELETE old Logo if exists

        return Redirect::back()->with(
            'message',
            [
                'type' => 'success',
                'text' => 'Logo Updated'
            ]
        ); 
    }

note: In this particular scenario (company logos) I'm aware that it probably doesn't matter if someone else gets access to the images. Please just assume they are sensitive.



Solution 1:[1]

You could add a route to serve the files and check if the current user is allowed to access the file.

use Illuminate\Support\Facades\Storage;

Route::get('files/{filename}', function (string $filename) {
    // Do your magic to check if the current user is allowed to access that file

    // Do your magic to determine the full path of the file
    $fullPath = '/some/directory/' . $filename;


    // Once we have the full path we can stream the contents of the file to the client
    return Storage::response($fullPath);
});

Unfortunately the Storage::response() method is undocumented as far as I know, but you can find it's implementation here: https://github.com/laravel/framework/blob/5.5/src/Illuminate/Filesystem/FilesystemAdapter.php

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Roj Vroemen