Simple upload with managing extension, filename & folders
Make sure to add enctype="multipart/form-data"
to the form so it can upload files. Add a file input with “name” attribute which will be used to pick file from the request.
<form enctype="multipart/form-data" method="POST" action="{{ route('register') }}">
<!-- other form fields -->
<input type="file" name="avatar" />
<!-- other form fields -->
</form>
In controller use hasFile
to check if there is a file with the name avatar
. Then store it in the avatars
folder with full path as /storage/app/avatars
.
The path stored in the database will be avatars/g7bMjJt3qPQNSvROBdtVS3BdYvqIhyi5Z6vujU79.png
. Which is random file name with the folder name.
// other functions
public function store(Request $request){
// save file to logged in $user
if($request->hasFile('avatar')){
$user->update([
'avatar' => $request->file('avatar')->store('avatars'),
]);
}
return view('profile.edit');
}
// other functions
Custom filename
Use the storeAs
instead of store
, the second parameter will be the filename. With custom filename you also need to pick the file extension.
if($request->hasFile('avatar')){
$file = $request->file('avatar');
$extension = $file->extension();
$user->update([
'avatar' => $file->storeAs('avatars', $user->id . '.' . $extension),
]);
}
Original filename by user
if($request->hasFile('avatar')){
$file = $request->file('avatar');
$filename = $file->getClientOriginalName();
$file->storeAs('avatars', $filename);
$user->update([
'avatar' => $filename,
]);
}
Original filename with unique separate folder
Here we are using the ID of the user as unique folder name so even if two users upload the files with the same name then it will not overwrite each others’ files.
if($request->hasFile('avatar')){
$file = $request->file('avatar');
$filename = $file->getClientOriginalName();
$file->storeAs('avatars/' . $user->id, $filename);
$user->update([
'avatar' => $filename,
]);
}
Storage folder and public/private files
Store files in public
folder with full path as /storage/app/public
.
// third parameter in `storeAs`
$file->storeAs('avatars', $filename, 'public');
// second parameter in `store`
$file->store('avatars', 'public');
These files are not inside root level public
folder and still inside the storage
folder. So to make the public folder accessible, use the artisan command to make this folder public.
Then file will be available as localhost:8000/storage/avatars/filename.png
.
php artisan storage:link
if you want to remove the storage
from the url, then change the value of public
array in file /config/filesystems.php
.
You can also specify the folder in public_path()
. Now file will be available directly as localhost:8080/uploads/avatars/filename.jpg
.
'disks' => [
// 'public' => [
// 'driver' => 'local',
// 'root' => storage_path('app/public'),
// 'url' => env('APP_URL').'/storage',
// 'visibility' => 'public',
// 'throw' => false,
// ],
'public' => [
'driver' => 'local',
'root' => public_path('uploads'),
'visibility' => 'public',
'throw' => false,
],
File Validation
$request->validate([
'name' => ['required', 'string', 'max:255'],
'avatar' => ['file', 'image', 'mimes:jpg', 'size:30', 'dimensions:min_width=2000,min_height:2000'],
]);
/**
* 'file' only accept files
* 'image' only accept image (pdf etc. not allowed)
* 'mimes' only accept specific mime types
* 'size' specify size in KB
* 'dimensions:min_width=2000,min_height:2000' specify min width and height
* 'dimensions:ratio=3/2' specify acceptable dimension in ratio
*/