Laravel 9 File Upload: How To Upload File In Laravel

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.

Laravel File Upload Example

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.

Laravel Dropzone File Upload Example

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
      ]);
    }
}

Laravel 5.6 File Upload Example Tutorial

You can see the uploaded file inside the Storage >> app >> files folder.

That’s it for this tutorial.

Recommended Posts

Laravel Dropzone Image Upload

Laravel Avatar Image Upload

Laravel Cloud File Upload

React and Laravel File Upload

Vue and Laravel File Upload

Laravel Multiple Files Upload

Laravel Multiple Images Upload

10 thoughts on “Laravel 9 File Upload: How To Upload File In Laravel”

  1. 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;

    })

    Reply
  2. 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.

    Reply

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.