How to Validate & Upload Multiple Image in Laravel 8

Throughout this tutorial, you will learn how to upload multiple files in Laravel 8 application, store all the images into the MySQL database. Likewise, we know how to validate multiple images before uploading to the server using Laravel built-in validate mechanism.

Image uploading is a usual process; every day, millions or billions of images get uploaded on various sites such as Facebook, Instagram, Twitter.

Laravel 8 Multiple Files & Images Upload Example

Multiple image upload provides the easy way for users to choose multiple images or files at once and upload all the files to the remote server.

File uploading is done through an HTML File input type, by default you can upload a single file but if you define multiple attributes with file input, then you can upload multiple files. Storing multiple files into the server requires a bit of programming and yes files uploaded on the server on HTTP POST method.

Following tasks are being taken care in this tutorial:

  • Multiple files and images upload
  • Implementing validation on file uploading
  • Show file uploading progress status
  • File uploading size limit upto 2mb
  • Store files in the database after uploading
  • Allow specific file types only for instance JPG, PNG, JPEG and GIF

Install Laravel Application

Installing a new Laravel project requires you to set up composer on your development system, create laravel application with below command:

composer create-project laravel/laravel --prefer-dist laravel-multiple-image-upload-example

Adding Database Details in ENV

Open .env configuration file, add database name, username and password:

DB_CONNECTION=mysql
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=db
DB_USERNAME=root
DB_PASSWORD=

Organize Model and Migrations

You have to create a new model, It allows you to create a new table inside the database.:

php artisan make:model File -m

Place the below code in app/Models/File.php migration file:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class File extends Model
{
    use HasFactory;
    protected $fillable = [
        'name',
        'path'
    ];
    
}

Next, define the table values in database/migrations/create_files_table file:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateFilesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('files', function (Blueprint $table) {
            $table->id();
            $table->string('name')->nullable();
            $table->string('path')->nullable();            
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('files');
    }
}

Run the command for migration:

php artisan migrate

Generating and Defining Controller

Controllers are the locus of all the core logic, the single controller class stores the code for HTTP requests which communicates with Routes, equally important Controllers resides in app/Http/Controllers folder.

Generate a new controller for Laravel 8 Multiple files or images uploading example:

php artisan make:controller FileController

Put the given below code in app/Http/Controllers/FileController.php:

<?php

namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\File;


class FileController extends Controller
{
    public function index(){
        return view('welcome');
    }
    
    public function uploadMultipleFiles(Request $req){
        $req->validate([
          'fileCollection' => 'required',
          'fileCollection.*' => 'mimes:jpeg,jpg,png,gif,csv,txt,xlx,xls,pdf|max:2048'
        ]);

        if($req->hasfile('fileCollection')) {
            foreach($req->file('fileCollection') as $file)
            {
                $name = $file->getClientOriginalName();
                $file->move(public_path().'/uploads/', $name);  
                $data[] = $name;  
            }

            $file= new File();
            $file->name=json_encode($data);
            $file->path=json_encode($data);
            
           
            $file->save();
   
           return back()->with('success', 'File uploaded');
        }            
    }

}

Defining Routes

Routes allow you to interact with controller code, which we are managing through two function. One for invoking view, another one for processing the file uploading.

So, add the below code in routes/web.php:

<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\FileController;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Route::get('/upload', [FileController::class, 'index']);

Route::post('/upload', [FileController::class, 'uploadMultipleFiles'])->name('upload.store');

Define Blade View

Now, you need to open resources\views\welcome.blade.php file, and put the below code within:

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css">

    <title>Laravel Multiple Files/Images Upload Example</title>
    <style>
        .container {
            max-width: 550px;
        }
    </style>
</head>

<body>

    <div class="container mt-5">
        <h3 class="text-center mb-5">Image Upload in Laravel</h3>
        <form action="{{route('upload.store')}}" method="post" enctype="multipart/form-data">
            @csrf
            @if ($message = Session::get('success'))
                <div class="alert alert-success">
                    <strong>{{ $message }}</strong>
                </div>
            @endif

            @if (count($errors) > 0)
                <div class="alert alert-danger">
                    <ul>
                        @foreach ($errors->all() as $error)
                        <li>{{ $error }}</li>
                        @endforeach
                    </ul>
                </div>
            @endif

            <div class="mb-3 text-center">
                <div class="preview"></div>
            </div>            

            <div class="custom-file">
                <input type="file" name="fileCollection[]" class="custom-file-input" id="multiImg" multiple="multiple">
                <label class="custom-file-label" for="images">Select File</label>
            </div>

            <button type="submit" name="submit" class="btn btn-danger btn-block mt-5">
                Upload
            </button>
        </form>
    </div>
  
    <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
    <script>
    $(function() {
        var imgPrev = function(input, imgPlaceholder) {

            if (input.files) {
                var allFiles = input.files.length;

                for (i = 0; i < allFiles; i++) {
                    var reader = new FileReader();

                    reader.onload = function(event) {
                        $($.parseHTML('<img>')).attr('src', event.target.result).appendTo(imgPlaceholder);
                    }

                    reader.readAsDataURL(input.files[i]);
                }
            }
        };

        $('#multiImg').on('change', function() {
            imgPrev(this, 'div.preview');
        });
    });    
    </script>
</body>
</html>

Upload Multiple Images/Files in Laravel

Eventually, you have almost completed everything related to this tutorial. Now, run the below command to start the project:

php artisan serve

Use the below URL:

http://127.0.0.1:8000/upload

Thats all for now; we have understood how to efficiently validate and upload multiple files & images in Laravel 8. Not just that, also how to store multiple uploaded files into the database.