To upload a file in Laravel, use the Storage::disk(‘local’)->putFileAs( ‘file name’) function. Laravel Flysystem integration delivers simple drivers for working with local filesystems, SFTP, and Amazon S3.
It is easy to switch between these storage options between your local development machine and production server, as the API remains the same for each system.
Apart from the backend, we will use the dropzone javascript library in the front end to drop a file in the form to upload it.
But first, let’s see the step-by-step guide to uploading a file in Laravel.
Step 1: Install Laravel
Type the following command.
laravel new fileupload
Go into the project folder and install the frontend dependencies.
npm install
Set up the Database inside the .env file.
The next step is to create an auth using the following command.
php artisan make:auth
Now, migrate the Database using the following command.
php artisan migrate
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() { Schema::create('files', function (Blueprint $table) { $table->increments('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'); } }
Now, 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.
Now, 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.
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');
Now, save the file and register the user; you can see this page.
Now 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() { 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 first need to 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 ]); } }
You can see the uploaded file inside the Storage >> app >> files folder.
That’s it for this tutorial.
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