How to Upload Multiple Images in Laravel

To upload multiple images in Laravel, use the “request” facade. You can upload an image with validation like images, mimes, max file upload, etc.

Here are the steps to upload multiple images in Laravel.

Step 1: Configuring Laravel

composer create-project laravel/laravel multipleimages --prefer-dist

Go to the .env file and add the database credentials.

Then we must create a migration file to store the image’s name. So go to the CMD and hit the following command.

php artisan make:migration create_forms_table

Define the schema as follows.

<?php

// create_forms_table.php

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

class CreateFormsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('forms', function (Blueprint $table) {
            $table->increments('id');
            $table->string('filename');
            $table->timestamps();
        });
    }

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

The next step will be to migrate this schema and make a table in the database.

php artisan migrate

We need to set up the controller and model file for our application. Type the following command to generate a model and controller.

php artisan make:model Form

php artisan make:controller FormController

It will generate two files.

  1. Form.php
  2. FormController.php

Step 2: Define routes in the web.php file.

Go to the routes  >>  web.php file and add the following routes.

// web.php

Route::get('form','FormController@create');
Route::post('form','FormController@store');

In the FormController, create a function and write the following code.

// FormController.php

/**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        //
        return view('create');
    }

Create a create.blade.php file inside the views folder.

<html lang="en">
<head>
  <title>Laravel Multiple File Upload Example</title>
  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.js"></script>
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
</head>
<body>
  
  <div class="container">
       
    <h3 class="jumbotron">Laravel Multiple File Upload</h3>
<form method="post" action="{{url('form')}}" enctype="multipart/form-data">
  {{csrf_field()}}

        <div class="input-group control-group increment" >
          <input type="file" name="filename[]" class="form-control">
          <div class="input-group-btn"> 
            <button class="btn btn-success" type="button"><i class="glyphicon glyphicon-plus"></i>Add</button>
          </div>
        </div>

        <button type="submit" class="btn btn-primary" style="margin-top:10px">Submit</button>

  </form>        
  </div>

</body>
</html>

Here, I have taken a straightforward form to add the images. However, we need functionality to populate the input field when we click the add button. So first, let us do that. We have used jQuery for that feature.

Step 3: Add the jQuery code to populate the input field.

After adding jQuery and some HTML codes to insert dynamic input fields, our file looks like this.

<html lang="en">
<head>
  <title>Laravel Multiple File Upload Example</title>
  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.js"></script>
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
</head>
<body>
   

  <div class="container">

    <h3 class="jumbotron">Laravel Multiple File Upload</h3>
<form method="post" action="{{url('form')}}" enctype="multipart/form-data">
  {{csrf_field()}}

        <div class="input-group control-group increment" >
          <input type="file" name="filename[]" class="form-control">
          <div class="input-group-btn"> 
            <button class="btn btn-success" type="button"><i class="glyphicon glyphicon-plus"></i>Add</button>
          </div>
        </div>
        <div class="clone hide">
          <div class="control-group input-group" style="margin-top:10px">
            <input type="file" name="filename[]" class="form-control">
            <div class="input-group-btn"> 
              <button class="btn btn-danger" type="button"><i class="glyphicon glyphicon-remove"></i> Remove</button>
            </div>
          </div>
        </div>

        <button type="submit" class="btn btn-primary" style="margin-top:10px">Submit</button>

  </form>        
  </div>


<script type="text/javascript">

    $(document).ready(function() {

      $(".btn-success").click(function(){ 
          var html = $(".clone").html();
          $(".increment").after(html);
      });

      $("body").on("click",".btn-danger",function(){ 
          $(this).parents(".control-group").remove();
      });

    });

</script>


</body>
</html>

Step 5: Add Laravel Image validation.

We are inserting multiple images, so; we need to make an array validation in our project. In a FormController.php file, add the following code to validate our input file.

// FormController.php

$this->validate($request, [
    'filename' => 'required',
    'filename.*' => 'image|mimes:jpeg,png,jpg,gif,svg|max:2048'
]);

It checks against the required field as well as the image type. If the input file does not contain an image or jpg, png, gif, or svg, it throws an error, and laravel catches it and displays these errors in the front end. To show errors in the form, we need to write the following code after the container class.

// create.blade.php

      @if (count($errors) > 0)
      <div class="alert alert-danger">
        <strong>Whoops!</strong> There were some problems with your input.<br><br>
        <ul>
          @foreach ($errors->all() as $error)
              <li>{{ $error }}</li>
          @endforeach
        </ul>
      </div>
      @endif

Here validation is done.

Laravel Form validation

Step 6: Insert multiple images in the database.

After checking the validation, we must store the image names in our database. So our final code to insert the various images into the database is the following.

// FormController.php

/**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)

    {

        $this->validate($request, [

                'filename' => 'required',
                'filename.*' => 'image|mimes:jpeg,png,jpg,gif,svg|max:2048'

        ]);
        
        if($request->hasfile('filename'))
         {

            foreach($request->file('filename') as $image)
            {
                $name=$image->getClientOriginalName();
                $image->move(public_path().'/images/', $name);  
                $data[] = $name;  
            }
         }

         $form= new Form();
         $form->filename=json_encode($data);
         
        
        $form->save();

        return back()->with('success', 'Your images has been successfully');
    }

If the input file is the image, it will loop through all the images individually, store the image names in the array, and then insert that array in the database.

I used json_encode() to insert the multiple-image names in one row.

You can make another table and then add the foreign key. After success, we need to display a success message. So write that code in the create.blade.php file.

// create.blade.php

 @if(session('success'))
   <div class="alert alert-success">
      {{ session('success') }}
   </div> 
 @endif

Our final create.blade.php file looks like this.

// create.blade.php

<html lang="en">
<head>
  <title>Laravel Multiple File Upload Example</title>
  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.js"></script>
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
</head>
<body>
  <div class="container">
      @if (count($errors) > 0)
      <div class="alert alert-danger">
        <strong>Whoops!</strong> There were some problems with your input.<br><br>
        <ul>
          @foreach ($errors->all() as $error)
              <li>{{ $error }}</li>
          @endforeach
        </ul>
      </div>
      @endif

        @if(session('success'))
        <div class="alert alert-success">
          {{ session('success') }}
        </div> 
        @endif

    <h3 class="jumbotron">Laravel Multiple File Upload</h3>
<form method="post" action="{{url('form')}}" enctype="multipart/form-data">
  {{csrf_field()}}

        <div class="input-group control-group increment" >
          <input type="file" name="filename[]" class="form-control">
          <div class="input-group-btn"> 
            <button class="btn btn-success" type="button"><i class="glyphicon glyphicon-plus"></i>Add</button>
          </div>
        </div>
        <div class="clone hide">
          <div class="control-group input-group" style="margin-top:10px">
            <input type="file" name="filename[]" class="form-control">
            <div class="input-group-btn"> 
              <button class="btn btn-danger" type="button"><i class="glyphicon glyphicon-remove"></i> Remove</button>
            </div>
          </div>
        </div>

        <button type="submit" class="btn btn-primary" style="margin-top:10px">Submit</button>

  </form>        
  </div>


<script type="text/javascript">


    $(document).ready(function() {

      $(".btn-success").click(function(){ 
          var html = $(".clone").html();
          $(".increment").after(html);
      });

      $("body").on("click",".btn-danger",function(){ 
          $(this).parents(".control-group").remove();
      });

    });

</script>
</body>
</html>

I have already put this code on Github.

Github Repository

36 thoughts on “How to Upload Multiple Images in Laravel”

  1. Thanks for the post it’s very helpfull if possible provide the Demo option here.
    So after seeing the Demo we can save or time to it’s meeting or requirment or not.

    Reply
      • thats true Krunal, but I think I have an observation, I’m new to this, but I think that when you add an image the js you use has some error because they do not add the names of the images as it should, nor less able to select more than one and list the images that were selected. Could you help me to fixed?

        Reply
  2. how to retrieve the data of json encode?
    for example i want to display the every image what should i do? i have tried json_decode but its not working properly on index method.

    Reply
  3. I have the same issue why is it saving only one image in the database? i use laravel 5.6 do you think is the problem ? thanks a lot.

    Dominic

    Reply
  4. Thanks !
    but why when i’ve been uploaded 3 images, it’s only save one filename/json in the Database, but in public folder it’s work, they save all the 3 images ?

    Reply
  5. Below are some corrections i did , if anyone want files to be saved with different id , instead of array also added time() in $name so it will stop messing with different images with same name.

    // Controller

    public function store(Request $request)

    {

    $this->validate($request, [

    ‘filename’ => ‘required’,
    ‘filename.*’ => ‘image|mimes:jpeg,png,jpg,gif,svg|max:2048’

    ]);

    if($request->hasfile(‘filename’))
    {

    foreach($request->file(‘filename’) as $image)
    {
    $form= new Form();

    $name=time().’.’.$image->getClientOriginalName();
    $image->move(public_path().’/images/’, $name);
    $data = $name;
    $form->filename=$data;
    $form->save();
    }

    }

    return back()->with(‘success’, ‘Your images has been successfully’);
    }

    Reply
  6. again and again it showing image field is reuired
    ?can anyone help me

    Add

    Remove

    Add

    Remove

    public function store(Request $request)
    {
    $request->validate([
    ‘service_center’ => ‘required’,
    ‘outcome’ => ‘required’,
    ‘cbdm_images’ => ‘required|image|mimes:jpeg,png,jpg,svg|max:2048’,
    ‘cbdm_file’ => ‘required|mimes:pdf,doc,excel’,
    ]);

    $cbdm_info = new Cbdm_details([
    $cbdm_info->service_center =$request->get(‘service_center’),
    $cbdm_info->outcome = $request->get(‘outcome’),
    $cbdm_info->cbdm_images = $request->file(‘cbdm_images’),
    $cbdm_info->cbdm_file = $request->file(‘cbdm_file’)
    ]);
    if($file = $request->file(‘cbdm_images’)) {
    $name = time() . $file->getClientOriginalName();
    $file->move(‘/cbdm-img-file’, $name);
    $photo = Cbdm_details::create([‘file’=>$name]);
    $input[‘cbdm_images’] = $photo->id;

    dd($file);
    }
    $cbdm_info->save();
    return redirect(‘admin/cbdm’)->with(‘success’, ‘Successfully Added CBDM Details!’);

    Reply
  7. In array only first file data is storing , what the issues please let me know its urgent

    Add

    Remove

    ‘cbdm_images.*’ => ‘image|mimes:jpeg,png,jpg,gif,svg|max:2048′,
    //’cbdm_file’ => ‘mimes:pdf,doc,.xlsx’
    ]);

    if($request->hasFile(‘cbdm_images’)){
    foreach($request->file(‘cbdm_images’) as $image){
    $filenameWithExt = $image->getClientOriginalName();
    $filename = pathinfo($filenameWithExt, PATHINFO_FILENAME);
    $extension = $image->getClientOriginalExtension();
    $fileNameToStore = $filename.’_’.time().’.’.$extension;
    $path = $image->storeAs(‘cbdm’,$fileNameToStore);
    $data[] = $fileNameToStore;
    dd($data);
    }
    }

    $cbdm_info->cbdm_images = json_encode($data);
    $cbdm_info->save();

    Reply
  8. nice. would be good to see how this saves in the dbase. does it create a row for each image with an id or does it save all the filenames in an array in 1 row?

    Reply
  9. $name=$image->getClientOriginalName();
    $image->move(public_path().’/properties/’, $name);
    $url= URL::to(‘/’) . ‘/properties/’ . $image->getClientOriginalName();
    $data[] = $url;
    Am storing the image location url to my database column call images.
    and the are in this form…
    [“http:\/\/kizflex.local\/properties\/10.jpg”,”http:\/\/kizflex.local\/properties\/11.jpg”]
    So how can iterate through this particular column so as to get each address and display it in my view?

    Reply
  10. if($request->hasfile(‘filename’))
    {

    foreach($request->file(‘filename’) as $image)
    {
    $name=$image->getClientOriginalName();
    $image->move(public_path().’/properties/’, $name);
    $url= URL::to(‘/’) . ‘/properties/’ . $image->getClientOriginalName();
    $data[] = $url;
    }
    }
    $property= new Property;
    $property->image=json_encode($data);
    $property->save();
    Am storing the image location url to my database column call images.
    and the are in this form…
    [“http:\/\/kizflex.local\/properties\/10.jpg”,”http:\/\/kizflex.local\/properties\/11.jpg”]

    So how can iterate through this particular column so as to get each address and display it in my view?
    Please am stuck i need help.

    Reply
  11. Hello, in what way could I show the images stored in a view?
    and tried:
    product-> image [0]
    product-> image [1]
    Without any result

    Reply
    • You can use like this code
      @foreach(json_decode($portfolio->slider, true) as $images)
      name}}”>
      @endforeach

      Reply
  12. display this error :
    LogicException in MimeTypeGuesser.php line 135:
    Unable to guess the mime type as no guessers are available (Did you enable the php_fileinfo extension?)

    Reply
  13. excuse me sir, i have a question,
    is possible to add some text field like a title image and the value automatically generate by file name?
    if possible, can you help me?

    Reply
  14. Hoping that someone is still reading this page’s comments…

    I tried entering the tutorial code as shown and couldn’t get it to run. I tried downloading the Github files and got it to run, but all it shows me is a page with a few links on it. The form for uploading files is not activating – as far as I can tell it’s not even getting created.

    I’m running in Windows using Laragon as a localhost server.

    Help, please?

    Reply

Leave a Comment

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