Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

n0tttrui's avatar

get storage url...

How can i get the url of storage avatar ? my code:

public function uploadAvatar () 
    {
        $avatar = request()->file('avatar')->store('avatars');
        $user = \Auth::user();
        $user->avatar = $avatar;
        $user->save();
        return back();
    }

if i use this:

{{ Storage::url(Auth::user()->avatar)}}

// return: /storage/avatars/fcdfa45ab020a63d95dd1f13b8e0f693.jpeg
// and not something like:
// http://sdsdsd.com/avatars/fcdfa45ab020a63d95dd1f13b8e0f693.jpeg
//why ?

Anyone can help ?

0 likes
8 replies
vogtdominik's avatar

Google`s first result for the term 'laravel storage image show from url' was http://stackoverflow.com/a/30191854/1614842

Which recommends to create a Controller Class, with a dedicated function to access files inside the storage folder, since its not visible to the public.

In your case, you should the following route and function.

Route::get('avatars/{filename}', function ($filename)
{
    // im not 100% sure about the $path thingy, you need to fiddle with this one around.
    $path = storage_path() . '/' . $filename;

    if(!File::exists($path)) abort(404);

    $file = File::get($path);
    $type = File::mimeType($path);

    $response = Response::make($file, 200);
    $response->header("Content-Type", $type);

    return $response;
});

Now you add a method to the User-Class, to return the avatar url.

public function getAvatarUrl(){
   // same thing as above for calling the url. Because $this->avatar will result in /storage/avatar/asduioajsdsd.png So it could lead to stripping some things of the string. Just wanted to give you the general idea.
   return url('avatars' . $this->avatar);
}

And call it whenever you need it

{{ Auth::user()->getAvatarUrl() }}

Nontheless you should also have a read here: https://laravel.com/docs/5.3/filesystem#retrieving-files Which suggests to store it in a public folder.

davielee's avatar

Using Storage::url($file) will only return a fully qualified path if you are using the s3 driver. If you are on the local driver, it is set to think you're storing files in a symlinked folder in your storage folder so all it needs to do is prepend /storage most of the time.

For any other storage method (at the time of writing) you're on your own to implement it. One possible solution is to stick it on the model itself.

class User extends Eloquent
{
    // First method uses accessors
    public function getAvatarAttribute($value)
    {
        return 'http://sdsdsd.com'.$value
    }

    // Second is using a dedicated method
    public function avatar()
    {
        return 'http://sdsdsd.com'.$this->avatar;
    }
}

Those can then be used in either of the following ways.

{{ $user->avatar }} 

or...

{{ $user->avatar() }}

Those are just some simple ways, and you could further extend it by making the base url an environment variable incase you need to switch it easily.

1 like
vogtdominik's avatar

@craigpaul i feel like your are running into the problem, that the resource is not accessible to the end user, because the resource folder is not inside the public folder and therefore not reachable through an url.

Thats why you need to return the file as a response through a route. Additionaly you can also add custom abstraction like access management or modifications to the original file.

1 like
davielee's avatar

@vogtdominik Well not me personally, when I use the local filesystem I just go with the route suggested in the docs. If it's on a storage method that isn't S3 or local, then all Laravel does is check if the adapter implements a getUrl method like below.

$adapter = $this->driver->getAdapter();

if (method_exists($adapter, 'getUrl')) {
    return $adapter->getUrl($path);
}

So the method I suggested above is just a quick and easy fix to get up and going. The best solution would be to have the adapter implement that getUrl method. Again like I said, I usually use S3 so Storage::url() works out of the box for that use case.

I guess it all really depends where and how @n0tttrui is saving the files.

vogtdominik's avatar

@craigpaul oh thats neat. So is it routing the file accordingly, if the file is local and in storage path or is it necessary to resolve the file by hand?

pmall's avatar

You just have to put a simlink from your public folder to your storage folder.

Example : public/avatars => storage/app/public/avatars. Then store your files in storage/app/public/avatar and access them from http://yourdomain.com/avatars/...

2 likes
davielee's avatar

@vogtdominik If you follow what Laravel is expecting to see for the local driver there is no need to resolve manually. The following is the logic for Laravel's LocalAdapter when calling Storage::url().

...
} elseif ($adapter instanceof LocalAdapter) {
    $config = $this->driver->getConfig();

    if ($config->has('url')) {
        return $config->get('url').'/'.$path;
    }

    $path = '/storage/'.$path;

    return Str::contains($path, '/storage/public') ?
            Str::replaceFirst('/public', '', $path) : $path
}

So basically, the driver will check if it has a url config and would just append the path to the url. That config is an instance of League\Flysystem\Config and that check will always "fail" because there is no config setup for that in Laravel by default.

Next it will just append '/storage/' to your path provided because the suggested method of handling files is by using that symlink. That will return to you a publicly accessible relative link which can be used in an image tag for example.

// $image = '/path/to/file.jpg';

<img src="{{ Storage::url($image) }}">

// That would end up having a src attribute equal to
// /storage/path/to/file.jpg
n0tttrui's avatar
n0tttrui
OP
Best Answer
Level 2

i solved the problem with something like that:

//Route (web.php)
Route::get('avatars/{user}', 'UserController@getAvatar');
//Controller:
public function getAvatar($name)
    {
        $user = User::where('name', '=', $name)->first();
        
        $path = storage_path('app/public/avatars/') . $user->avatar;
    
        if(!File::exists($path)) 
            $path = storage_path('app/public/avatars/') . 'default.png';

        $file = File::get($path);
        $type = File::mimeType($path);

        $response = Response::make($file, 200);
        $response->header("Content-Type", $type);

        return $response;
    }

Please or to participate in this conversation.