Laravel File Uploads: Save Filename in DB with Folder and URL?

https://laraveldaily.com/storage/423/Copy-of-Copy-of-ModelpreventLazyLoading();-(6).png

When uploading files with Laravel, how to store the filename in the DB? Should you store filename.png? Or, include the folder of avatars/filename.png? Or, the full path https://website.com/avatars/filename.png? Let me tell you my opinion.

This tutorial will have an avatar field on the register page and an avatar column in the users table. Let’s see how we can save it.


The easiest way is to store just the filename and create a separate storage disk.

config/filesystems.php:

return [

 

// ...

 

'disks' => [

 

// ...

 

'avatars' => [

'driver' => 'local',

'root' => storage_path('app/public/avatars'),

'url' => env('APP_URL').'/storage/avatars',

'visibility' => 'public',

'throw' => false,

],

 

],

 

// ...

 

];

Then, when storing the file we need to specify the new avatars disk.

app/Http/Controllers/Auth/RegisteredUserController.php:

class RegisteredUserController extends Controller

{

// ...

 

public function store(Request $request): RedirectResponse

{

$request->validate([

'name' => ['required', 'string', 'max:255'],

'email' => ['required', 'string', 'email', 'max:255', 'unique:'.User::class],

'password' => ['required', 'confirmed', Rules\Password::defaults()],

'avatar' => ['nullable', 'image'],

]);

 

if ($request->hasFile('avatar')) {

$avatar = $request->file('avatar')->store(options: 'avatars');

}

 

$user = User::create([

'name' => $request->name,

'email' => $request->email,

'password' => Hash::make($request->password),

'avatar' => $avatar ?? null,

]);

 

// ...

}

}

This way, your full URL filename https://website.com/storage/avatars/filename.png consists of three things:

  • Domain: https://website.com is stored in your APP_URL in .env file: so it is flexibly different for your local and production servers
  • Folder: /storage/avatars is in the config('disks.avatars.url') which corresponds to the internal structure of /storage/app/public/avatars described in the same config file. Both also can be flexibly changed if needed.
  • Filename: filename.png is the only thing actually landing in the DB column

To get the URL for the image in the Blade file, we would use URL method on the Storage facade providing the disk.

<img src="" alt="" />

But what if, after some time, you would need to go from local disks to, let’s say, Amazon S3?

The only change you would need to make is to change the disk, and maybe instead of the url, use the temporaryUrl method to provide the expiration time for the link.

<img src="" alt="" />

Laravel News Links