Chat with us, powered by LiveChat

This website uses cookies

Our website, platform and/or any sub domains use cookies to understand how you use our services, and to improve both your experience and our marketing relevance.

How to Upload Multiple Images and Files in Laravel with Validation

December 7, 2018

7 Min Read
laravel file upload
Reading Time: 7 minutes

File upload is an essential aspect of any project. Given this importance, it is surprising that many developers face challenges of adding file upload feature to their projects. In particular, developers are unsure about how to upload and validate files.

In this tutorial, I will discuss how to implement Laravel file upload functionality with multiple file and image uploading option. I will use the Laravel storage folder and then create database record for uploading files. I will use Laravel 5.5 and Bootstrap to power the code of this tutorial.

You might also like: PHP File Upload with jQuery AJAX

Prerequisites

For the purpose of this tutorial, I assume that you have a Laravel application installed on a web server. My setup is:

  • Linux/Unix or WAMP/XAMPP environment
  • Laravel 5.5
  • PHP 7.1
  • MySQL
  • Web server (Apache, NGINX or integrated PHP web server for testing)

I have installed a Laravel app on a Cloudways managed Laravel server because it has everything I’ll need for this tutorial. If you do not have an account on Cloudways, sign up for free, and check out the following GIF to setup the server and application in just a few clicks.

Create Model with Migration

I will start by creating the model and the tables in which I will save the files.

Launch the SSH terminal, go to the application’s public root folder and type following commands:

php artisan make:model Item -m
php artisan make:model ItemDetails -m

Item Model

When the migration and the model have been created successfully, go to app/Item.php and add the following Model code to it:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Item extends Model

{

protected $fillable = ['name'];

}

Create the Migration

Go to the database/migration folder and open the migration file for item. You will see the default structure that include (in my case) id , name, timestamps.

<?php

use Illuminate\Support\Facades\Schema;

use Illuminate\Database\Schema\Blueprint;

use Illuminate\Database\Migrations\Migration;

class CreateItemsTable extends Migration

{

public function up()

{

Schema::create('items', function (Blueprint $table) {

$table->increments('id');

$table->string('name');

$table->timestamps();

});

}

public function down()

{

Schema::drop('items');

}

}?>

Model Of ItemDetails

The model comprises of the following code:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class ItemDetail extends Model

{

protected $fillable = ['item_id', 'filename'];

public function item()

{

return $this->belongsTo('App\Item');

}

}

?>

In the above code, I used belongTO because itemDetails belongs to Item table and item_id is the foreign key. This is known as inverse relation in Laravel.

Migration of ItemDetails Table

Go to the database/migration folder and open the migration file for itemdetails. You will see the default structure that include id , name . timestamps.

<?php

use Illuminate\Support\Facades\Schema;

use Illuminate\Database\Schema\Blueprint;

use Illuminate\Database\Migrations\Migration;

class CreateItemDetailsTable extends Migration

{

/**

* Run the migrations.

*

* @return void

*/

public function up()

{

Schema::create('item_details', function (Blueprint $table) {

$table->increments('id');

$table->integer('item_id')->unsigned();

$table->foreign('item_id')->references('id')->on('items');

$table->string('filename');

$table->timestamps();

});

}

public function down()

{

Schema::drop('item_details');

}

}

?>

 

Next , In the app/Providers/AppServiceProvider.php file, the boot method set a default string length:

use Illuminate\Support\Facades\Schema;

public function boot()

{

Schema::defaultStringLength(191);

}

Database Configuration

In a Laravel powered app, database configuration is handled by two files: env and config/database.php. In my case, I created a database with the name uploading. The Cloudways Database Manager makes the entire process very easy.

Next, run the following command in the terminal to create tables in the database:

php artisan migrate

Now, when you check the database, you will see that the tables have been created  successfully.

You might also like: Connect Laravel with Firebase Real Time Database

Set up the Route

Route sets the application URL and the controller method for this URL. Routes are located in route/web.php and contains the following code:

Route::get('/multiuploads', 'UploadController@uploadForm');

Route::post('/multiuploads', 'UploadController@uploadSubmit');

Get Your VueJS Handbook Now

Simple enter your email address and get the download link in your Inbox.

Thank You

Your Ebook is on it’s Way to Your Inbox.

Create the Controller

Next, create the Controller by using the following command:

php artisan make:controller UploadController

Next, go to app/Http/Controller/UploadController and open the Controller file. Add the following code to it:

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class UploadController extends Controller

{

public function uploadForm()

{

return view('upload_form');

}

public function uploadSubmit(Request $request)

{

// coding ….

}

}

View File (Upload_form.blade.php)

In the view file, I have used Bootstrap for styling the code, link stylesheet , jQuery, JavaScript files.

<!doctype html>

<html lang="{{ app()->getLocale() }}">

<head>

<meta charset="utf-8">

<meta http-equiv="X-UA-Compatible" content="IE=edge">

<meta name="viewport" content="width=device-width, initial-scale=1">

<title>Laravel Uploading</title>

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

<!-- Optional theme -->

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">

<!-- Fonts -->

<link href="https://fonts.googleapis.com/css?family=Raleway:100,600" rel="stylesheet" type="text/css">

<!-- Styles -->

<style>

.container {

margin-top:2%;

}

</style>

</head>

<body>

@if (count($errors) > 0)

<div class="alert alert-danger">

<ul>

@foreach ($errors->all() as $error)

<li>{{ $error }}</li>

@endforeach

</ul>

</div>

@endif

<div class="container">

<div class="row">

<div class="col-md-2"> <img src="/32114.svg" width="80" /></div>

<div class="col-md-8"><h2>Laravel Multiple File Uploading With Bootstrap Form</h2>

</div>

</div>

<br>

<div class="row">

<div class="col-md-3"></div>

<div class="col-md-6">

<form action="/multiuploads" method="post" enctype="multipart/form-data">

{{ csrf_field() }}

<div class="form-group">

<label for="Product Name">Product Name</label>

<input type="text" name="name" class="form-control"  placeholder="Product Name" >

</div>

<label for="Product Name">Product photos (can attach more than one):</label>

<br />

<input type="file" class="form-control" name="photos[]" multiple />

<br /><br />

<input type="submit" class="btn btn-primary" value="Upload" />

</form>

</div>

</div>

</div>

</body>

</html>

Controller with Validation

I have use Bootstrap classes for showing the alert for validation and use Laravel Validation methods to validate the type of file. Use the following code for the controller:

<?php

namespace App\Http\Controllers;

use App\Item;

use App\ItemDetail;

use Illuminate\Http\Request;

class UploadController extends Controller

{

public function uploadForm()

{

return view('upload_form');

}

public function uploadSubmit(Request $request)

{

$this->validate($request, [

'name' => 'required',

'photos'=>'required',

]);

if($request->hasFile('photos'))

{

$allowedfileExtension=['pdf','jpg','png','docx'];

$files = $request->file('photos');

foreach($files as $file){

$filename = $file->getClientOriginalName();

$extension = $file->getClientOriginalExtension();

$check=in_array($extension,$allowedfileExtension);

//dd($check);

if($check)

{

$items= Item::create($request->all());

foreach ($request->photos as $photo) {

$filename = $photo->store('photos');

ItemDetail::create([

'item_id' => $items->id,

'filename' => $filename

]);

}

echo "Upload Successfully";

}

else

{

echo '<div class="alert alert-warning"><strong>Warning!</strong> Sorry Only Upload png , jpg , doc</div>';

}

}

}

}

}?>

Storing Data and Files in Laravel

Laravel provides a storage filesystem that stores all the data including files and images.

For this, Laravel provides config/filesystems.php, located in the config folder. In this file, you can specify the locations for your file storage.

return [

'default' => 'local',

'disks' => [

'local' => [

'driver' => 'local',

'root' => storage_path('app'),

],

// ...

 

Using the above code snippet, you could save the files in app/storage folder instead of the public folder. This is a good coding practice for storing data because this location is inaccessible from the browser. For the purpose of this tutorial, I have created a folder with the name photos in storage/app/.

When the run the app in the browser, you will see the following screens:

With Validation

laravel file upload validation

laravel multiple file upload form

laravel file upload error

To see the image and file upload in Laravel in action, check out the demo.

Difference Between Local and Public Disks

You can see the disks local and public defined in config/filesystems.php. Laravel uses the local disk configuration by default. The underlying difference between local and public disk is that local disk is private and can’t be accessed from the browser, whereas the public disk can be easily accessed from the browser.

Since the public disk is in storage/app/public and Laravel’s server root is in public, you need to link storage/app/public to Laravel’s public folder. We can do by running php artisan storage:link.

Manipulating files

Laravel largely needs external help in resizing images, adding filters and other related operations. Adding these feature to the native environment of Laravel will only bloat the application since there isn’t any installs needed. For that, we need a package called intervention/image. Earlier above, we have already installed this package, but still composer requires it for reference.

We don’t need to register anything since Laravel can automatically detect packages. Read the following if you are using lesser version than Laravel 5.5.

To resize an image

$image = Image::make(storage_path('app/public/profile.jpg'))->resize(300, 200);

Even Laravel’s packages are fluent.

Sending Files as Email Attachments

For send files with attachments you just paste the following code in your controller according to input fields.

<?php

...

...

public function uploadDocument(Request $request) {

   $title = $request->file('name');

   

   // Get the uploades file with name document

   $document = $request->file('document');



   // Required validation

   $request->validate([

       'name' => 'required|max:255',

       'document' => 'required'

   ]);



   // Check if uploaded file size was greater than

   // maximum allowed file size

   if ($document->getError() == 1) {

       $max_size = $document->getMaxFileSize() / 1024 / 1024;  // Get size in Mb

       $error = 'The document size must be less than ' . $max_size . 'Mb.';

       return redirect()->back()->with('flash_danger', $error);

   }

   

   $data = [

       'document' => $document

   ];

   

   // If upload was successful

   // send the email

   $to_email = test@example.com;

   \Mail::to($to_email)->send(new \App\Mail\Upload($data));

   return redirect()->back()->with('flash_success', 'Your document has been uploaded.');

}

Create email sender class

To send the email in Laravel, you need to create a separate class file. This class will have the functionality to prepare email and its body. Also we will attach the uploaded file as inline attachment.

Here is my email class:

<?php

#App\Mail\Upload.php

namespace App\Mail;

use Illuminate\Bus\Queueable;

use Illuminate\Mail\Mailable;

use Illuminate\Queue\SerializesModels;

class Upload extends Mailable

{

   use Queueable, SerializesModels;

   protected $data;

   /**

    * Create a new message instance.

    *

    * @return void

    */

   public function __construct($data=[])

   {

       $this->data = $data;

   }



   /**

    * Build the message.

    *

    * @return $this

    */

   public function build()

   {

       return $this->view('emails/upload')

               ->subject('Document Upload')

               ->attach($this->data['document']->getRealPath(),

               [

                   'as' => $this->data['document']->getClientOriginalName(),

                   'mime' => $this->data['document']->getClientMimeType(),

               ]);

   }

}

The important functions used here are:

– getRealPath(): Get the temporary upload path

– getClientOriginalName(): Get the name of uploaded file

– getClientMimeType(): Get the mime type of uploaded file

Create the email template

In the above step, our email class refers to the email template as return $this->view(’emails/upload’). So we will create the email template at resources/views/emails/upload.blade.php

#resources/views/emails/upload.blade.php

<p>Hi,</p>

<p>Please download the attached file.</p>

<p>Thanks</p>

Now when you submit the form, your uploaded file will be sent an email attachment.

Share your opinion in the comment section. COMMENT NOW

Share This Article

Launch Laravel apps with 1-Click Install. Painless Server Management

Deploy your apps on optimized Laravel hosting servers.

Pardeep Kumar

Pardeep is a PHP Community Manager at Cloudways - A Managed PHP Hosting Platform. He love to work on Open source platform , Frameworks and working on new ideas. You can email him at pardeep.kumar@cloudways.com

Get Our Newsletter
Be the first to get the latest updates and tutorials.

Do you like what you read?

Get the Latest Updates

Share Your Feedback

Please insert Content

Thank you for your feedback!