To upload a file in Laravel 10, use the “Storage::disk(‘local’)->putFileAs( ‘file name’)” function. Laravel Flysystem integration delivers simple drivers for working with local filesystems, SFTP, and Amazon S3.
Here is the step-by-step guide to uploading a file in Laravel.
Step 1: Install Laravel
laravel new fileupload
Go inside the folder.
Install Laravel UI Package using the below command.
composer require laravel/ui --dev
Now add Bootstrap with auth scaffolding.
php artisan ui bootstrap --auth
Run the below commands one by one.
npm install
npm run build
Step 2: Create a file table.
We need to create a File model and migrations using the following command.
php artisan make:model File -m
Define the schema inside the newly created migration file.
// create_files_table <?php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateFilesTable extends Migration { /** * Run the migrations. * * @return void */ public function up(): void { Schema::create('files', function (Blueprint $table) { $table->id(); $table->integer('user_id')->unsigned()->index(); $table->string('title'); $table->text('overview'); $table->decimal('price', 6, 2); $table->timestamps(); $table->softDeletes(); $table->foreign('user_id') ->references('id') ->on('users') ->onDelete('cascade'); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('files'); } }
Migrate using the following command.
php artisan migrate
The next step is to build a relationship between the User and File models.
Inside File.php, write the following code.
<?php // File.php namespace App; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\SoftDeletes; class File extends Model { use SoftDeletes; protected $fillable = [ 'title', 'overview', 'price' ]; public function user() { return $this->belongsTo(User::class); } }
Here we have stated that every file belongs to a particular User.
Define the Relationship inside the User.php model.
<?php // User.php namespace App; use Illuminate\Notifications\Notifiable; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable { use Notifiable; /** * The attributes that are mass assignable. * * @var array */ protected $fillable = [ 'name', 'email', 'password', ]; /** * The attributes that should be hidden for arrays. * * @var array */ protected $hidden = [ 'password', 'remember_token', ]; public function files() { return $this->hasMany(File::class); } }
Step 3: Create a View and Route for uploading files.
The base app.blade.php file looks like this:
<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- CSRF Token -->
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>{{ config('app.name', 'Laravel') }}</title>
<!-- Fonts -->
<link rel="dns-prefetch" href="//fonts.bunny.net">
<link href="https://fonts.bunny.net/css?family=Nunito" rel="stylesheet">
<!-- Scripts -->
@vite(['resources/sass/app.scss', 'resources/js/app.js'])
</head>
<body>
<div id="app">
<nav class="navbar navbar-expand-md navbar-light bg-white shadow-sm">
<div class="container">
<a class="navbar-brand" href="{{ url('/') }}">
{{ config('app.name', 'Laravel') }}
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="{{ __('Toggle navigation') }}">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<!-- Left Side Of Navbar -->
<ul class="navbar-nav me-auto">
</ul>
<!-- Right Side Of Navbar -->
<ul class="navbar-nav ms-auto">
<!-- Authentication Links -->
@guest
@if (Route::has('login'))
<li class="nav-item">
<a class="nav-link" href="{{ route('login') }}">{{ __('Login') }}</a>
</li>
@endif
@if (Route::has('register'))
<li class="nav-item">
<a class="nav-link" href="{{ route('register') }}">{{ __('Register') }}</a>
</li>
@endif
@else
<li class="nav-item dropdown">
<a id="navbarDropdown" class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false" v-pre>
{{ Auth::user()->name }}
</a>
<div class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdown">
<a class="dropdown-item" href="{{ route('logout') }}"
onclick="event.preventDefault();
document.getElementById('logout-form').submit();">
{{ __('Logout') }}
</a>
<form id="logout-form" action="{{ route('logout') }}" method="POST" class="d-none">
@csrf
</form>
</div>
</li>
@endguest
</ul>
</div>
</div>
</nav>
<main class="py-4">
@yield('content')
</main>
</div>
</body>
</html>
Create a FileController using the following command.
php artisan make:controller FileController
Inside the home.blade.php file, write the following code inside.
@extends('layouts.app') @section('content') <div class="container"> <div class="row justify-content-center"> <div class="col-md-8"> <div class="card"> <div class="card-header">File Upload</div> <div class="card-body"> <form method="POST" action="{{ route('file.upload') }}" aria-label="{{ __('Upload') }}"> @csrf <div class="form-group row"> <label for="title" class="col-sm-4 col-form-label text-md-right">{{ __('Title') }}</label> <div class="col-md-6"> <input id="title" type="text" class="form-control{{ $errors->has('title') ? ' is-invalid' : '' }}" name="title" value="{{ old('title') }}" required autofocus /> @if ($errors->has('title')) <span class="invalid-feedback" role="alert"> <strong>{{ $errors->first('title') }}</strong> </span> @endif </div> </div> <div class="form-group row"> <label for="overview" class="col-sm-4 col-form-label text-md-right">{{ __('Overview') }}</label> <div class="col-md-6"> <textarea id="overview" cols="10" rows="10" class="form-control{{ $errors->has('overview') ? ' is-invalid' : '' }}" name="overview" value="{{ old('overview') }}" required autofocus></textarea> @if ($errors->has('overview')) <span class="invalid-feedback" role="alert"> <strong>{{ $errors->first('overview') }}</strong> </span> @endif </div> </div> <div class="form-group row"> <label for="price" class="col-md-4 col-form-label text-md-right">{{ __('Price') }}</label> <div class="col-md-6"> <input id="price" type="text" class="form-control{{ $errors->has('price') ? ' is-invalid' : '' }}" name="price" required> @if ($errors->has('price')) <span class="invalid-feedback" role="alert"> <strong>{{ $errors->first('price') }}</strong> </span> @endif </div> </div> <div class="form-group row mb-0"> <div class="col-md-8 offset-md-4"> <button type="submit" class="btn btn-primary"> {{ __('Upload') }} </button> </div> </div> </form> </div> </div> </div> </div> </div> @endsection
Also, you need to define the Post route inside routes >> web.php file.
<?php // web.php Route::get('/', function () { return view('welcome'); }); Auth::routes(); Route::get('/home', 'HomeController@index')->name('home'); Route::post('file/upload', 'FileController@store')->name('file.upload');
Save the file and register the user; you can see this page.
You can see that we have not yet used any file form field from the form. We will do it in a minute, but this is our primary form setup.
Step 4: Storing the form data.
We need to write the store function to save the data in the Database.
<?php // FileController.php namespace App\Http\Controllers; use Illuminate\Http\Request; class FileController extends Controller { public function store(Request $request) { $request->validate([ 'title' => 'required:max:255', 'overview' => 'required', 'price' => 'required|numeric' ]); auth()->user()->files()->create([ 'title' => $request->get('title'), 'overview' => $request->get('overview'), 'price' => $request->get('price') ]); return back()->with('message', 'Your file is submitted Successfully'); } }
We have also included the validation for our form fields.
Also, we need to update our view to see the flash message.
// home.blade.php @if(session()->get('message')) <div class="alert alert-success"> {{ session()->get('message') }} </div> @endif
Step 5: Setup File Upload Relationship.
We will create another model and migration for the uploading files.
Type the following command to generate the model and migration.
php artisan make:model Upload -m
Write the following schema inside <timestamp>create_uploads_table.php file.
// create_uploads_table.php public function up(): void { Schema::create('uploads', function (Blueprint $table) { $table->increments('id'); $table->integer('user_id')->unsigned()->index(); $table->string('filename'); $table->softDeletes(); $table->timestamps(); $table->foreign('user_id') ->references('id') ->on('users') ->onDelete('cascade'); }); }
Migrate the Database using the following command.
php artisan migrate
Now we need to set up the relationships.
Inside the Upload.php file, write the following code.
<?php // Upload.php namespace App; use Illuminate\Database\Eloquent\Model; class Upload extends Model { protected $fillable = [ 'filename' ]; public function user() { return $this->belongsTo(User::class); } }
Here, Upload is belongsTo File and User.
Write the following relationship methods inside the User.php model.
// User.php public function files() { return $this->hasMany(File::class); } public function uploads() { return $this->hasMany(Upload::class); }
Finally, write the following relationships inside the File.php model.
// File.php public function user() { return $this->belongsTo(User::class); }
Step 6: Set up the Dropzone.
Install the Dropzone library using the following command.
npm install dropzone --save
Include this library inside resources >> assets >> js >> bootstrap.js file.
We need to add the code inside that file.
// bootstrap.js /** * Dropzone */ window.Dropzone = require('dropzone'); Dropzone.autoDiscover = false;
We need to import the Dropzone CSS files. So inside resources >> assets >> sass >> app.scss file, add the following code.
// app.scss // Fonts @import url('https://fonts.googleapis.com/css?family=Nunito'); // Variables @import 'variables'; // Bootstrap @import '~bootstrap/scss/bootstrap'; // Dropzone @import '~dropzone/dist/min/dropzone.min.css'; .dropzone { margin-bottom: 20px; min-height: auto; }
Compile the file using the following command.
npm run dev
We need to use the Dropzone library inside the home.blade.php file.
@extends('layouts.app') @section('content') <div class="container"> <div class="row justify-content-center"> <div class="col-md-8"> @if(session()->get('message')) <div class="alert alert-success"> {{ session()->get('message') }} </div> @endif <div class="card"> <div class="card-header">File Upload</div> <div class="card-body"> <form method="POST" action="{{ route('file.upload') }}" aria-label="{{ __('Upload') }}"> @csrf <div class="form-group row "> <label for="title" class="col-sm-4 col-form-label text-md-right">{{ __('File Upload') }}</label> <div class="col-md-6"> <div id="file" class="dropzone"></div> </div> </div> <div class="form-group row"> <label for="title" class="col-sm-4 col-form-label text-md-right">{{ __('Title') }}</label> <div class="col-md-6"> <input id="title" type="text" class="form-control{{ $errors->has('title') ? ' is-invalid' : '' }}" name="title" value="{{ old('title') }}" required autofocus /> @if ($errors->has('title')) <span class="invalid-feedback" role="alert"> <strong>{{ $errors->first('title') }}</strong> </span> @endif </div> </div> <div class="form-group row"> <label for="overview" class="col-sm-4 col-form-label text-md-right">{{ __('Overview') }}</label> <div class="col-md-6"> <textarea id="overview" cols="10" rows="10" class="form-control{{ $errors->has('overview') ? ' is-invalid' : '' }}" name="overview" value="{{ old('overview') }}" required autofocus></textarea> @if ($errors->has('overview')) <span class="invalid-feedback" role="alert"> <strong>{{ $errors->first('overview') }}</strong> </span> @endif </div> </div> <div class="form-group row"> <label for="price" class="col-md-4 col-form-label text-md-right">{{ __('Price') }}</label> <div class="col-md-6"> <input id="price" type="text" class="form-control{{ $errors->has('price') ? ' is-invalid' : '' }}" name="price" required> @if ($errors->has('price')) <span class="invalid-feedback" role="alert"> <strong>{{ $errors->first('price') }}</strong> </span> @endif </div> </div> <div class="form-group row mb-0"> <div class="col-md-8 offset-md-4"> <button type="submit" class="btn btn-primary"> {{ __('Upload') }} </button> </div> </div> </form> </div> </div> </div> </div> </div> @endsection @section('scripts') <script> var drop = new Dropzone('#file', { url: "{{ route('upload') }}" }); </script> @endsection
Also, define the POST route to upload a file.
// web.php Route::post('upload', 'FileController@upload')->name('upload');
Create an upload function inside the FileController.php file.
// FileController.php public function upload() { return 'x'; }
Save the file and go to http://fileupload.test/home.
Step 7: Handling File Upload Process.
We must first add the headers while sending a POST request to the server.
// home.blade.php @section('scripts') <script> var drop = new Dropzone('#file', { createImageThumbnails: false, addRemoveLinks: true, url: "{{ route('upload') }}", headers: { 'X-CSRF-TOKEN': document.head.querySelector('meta[name="csrf-token"]').content } }); </script> @endsection
The final code for the FileController.php file looks like below.
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use Illuminate\Support\Facades\Storage; use App\Upload; class FileController extends Controller { public function store(Request $request) { $request->validate([ 'title' => 'required:max:255', 'overview' => 'required', 'price' => 'required|numeric' ]); auth()->user()->files()->create([ 'title' => $request->get('title'), 'overview' => $request->get('overview'), 'price' => $request->get('price') ]); return back()->with('message', 'Your file is submitted Successfully'); } public function upload(Request $request) { $uploadedFile = $request->file('file'); $filename = time().$uploadedFile->getClientOriginalName(); Storage::disk('local')->putFileAs( 'files/'.$filename, $uploadedFile, $filename ); $upload = new Upload; $upload->filename = $filename; $upload->user()->associate(auth()->user()); $upload->save(); return response()->json([ 'id' => $upload->id ]); } }
The uploaded file is inside the Storage >> app >> files folder.
That’s it for this tutorial.

Krunal Lathiya is a seasoned Computer Science expert with over eight years in the tech industry. He boasts deep knowledge in Data Science and Machine Learning. Versed in Python, JavaScript, PHP, R, and Golang. Skilled in frameworks like Angular and React and platforms such as Node.js. His expertise spans both front-end and back-end development. His proficiency in the Python language stands as a testament to his versatility and commitment to the craft.
Thanks
File upload functionality is not working by drag option. Do we need to do separate code for Linux system? Regards Ranga
For uploading file in laravel, we can simply make a trait and use it in any model and do the file upload.
It does not work I don’t have that title “Drop files here to upload”
I have css and js compiled
me to, what did you do to fix this error
Howdy, npm dropzone is not compatible with ubuntu. any alternative of this ?
hi my dropzone is not working when new Dropzone on scripts section why?
use dropzone cdn
$(document).ready(function () {
var drop = new Dropzone(‘.dropzone’, {
uploadMultiple: true,
parallelUploads: 2,
maxFilesize: 16,
previewTemplate: document.querySelector(‘#preview’).innerHTML,
addRemoveLinks: true,
dictRemoveFile: ‘Remove file’,
dictFileTooBig: ‘Image is larger than 16MB’,
timeout: 10000,
init: function () {
this.on(“removedfile”, function (file) {
$.post({
url: ‘/images-delete’,
data: {id: file.name, _token: $(‘[name=”_token”]’).val()},
dataType: ‘json’,
success: function (data) {
total_photos_counter–;
$(“#counter”).text(“# ” + total_photos_counter);
}
});
});
},
success: function (file, done) {
total_photos_counter++;
$(“#counter”).text(“# ” + total_photos_counter);
}
})
var total_photos_counter = 0;
})
Thank you for this good tutorial. Please note that you forgot to add enctype=”multipart/form-data” to the form, so the file field won’t be sent.
can i send a larg file with this app 2GB video
Great post! I was wondering how to do this in Laravel. Thanks for the tutorial!
Hello, i made this in Laravel 10 and get a Error 500 after Step 3.
If i open the subpage /home i just see the 500error 🙁
Any Ideas?