File or image upload in laravel 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 10 and Bootstrap to power the code of this tutorial.
- How to Upload Multiple Files in Laravel with Validation
- Migration of ItemDetails Table
- How to Create the Controller
- How to Create File Upload Form
- Storing Data and Files in Laravel With Validation
- What is the Difference Between Local and Public Disks?
- How Sending Files as Email Attachments
- Create the Email Template
Elevate Your Laravel Hosting With Cloudways!
Unlock unmatched performance, scalability, and ease of management for your web applications!
How to Upload Multiple Files in Laravel with Validation
Uploading multiple files in laravel with validation is a streamlined process that enhances the integrity and security of your application. Laravel’s file validation not only simplifies the process of handling multiple file uploads but also ensures that only files meeting your specified criteria are accepted.
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 10
- PHP 8.x
- MySQL / MariaDB
- 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, to explore the seamless world of Laravel hosting & check out the following GIF to setup the server and application in just a few clicks.
How to 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
How to Create 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']; }
How to 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');
Unlock Laravel Power: Easy Validation, Zero Server Pains
Simplify your workflows, ditch server management, and focus on building. Cloudways makes Laravel validation a breeze.
How to 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 …. } }
How to Create File Upload Form
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>
How to 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 With Validation
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:
Resize Image
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.
To resize an image
$image = Image::make(storage_path('app/public/profile.jpg'))->resize(300, 200);
Even Laravel’s packages are fluent.
What is the 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.
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 = [email protected]; \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
Transform your Laravel experience with Cloudways
Turbocharge your development process with our streamlined platform, Cloudways provides the tools and support you need to succeed. Experience hosting like never before!
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.
Q) How to validate multiple image upload in Laravel?
A) To validate multiple image uploads in Laravel,
- start by ensuring your form includes and uses an input field named with an array notation to allow multiple file selections.
- In your controller, you need to use Laravel’s validation feature by calling the validate method on the incoming request.
- Specify your validation rules for the images array in your functions.
This approach ensures that all uploaded files adhere to your specified validation criteria, enhancing the integrity and reliability of the file upload process in your Laravel application.
Q) How to handle multiple file upload in Laravel?
A) Handling multiple file uploads is simple task that can be achieved using Laravel’s built-in features along with some simple HTML markup and possibly JavaScript. Here’s a basic steps that you can follow to upload multiple images in laravel.
- Create a form in your Blade view that allows users to select multiple files for upload.
- Define a route to handle the file uploads in your routes/web.php file
- Create a controller to handle the file upload logic. You can generate a controller using Artisan command-line tool.
- Handle File Upload Logic
- Display Validation Errors
- Display Success or Failure Messages
Q) Are there any Laravel packages or libraries available for handling multiple file uploads?
A) Yes, there are many Laravel packages and libraries available for handling multiple file uploads, such as “Laravel Filemanager,” “Laravel Medialibrary,” and “Dropzone.js Laravel.” These packages provide convenient features and functionalities for managing and handling multiple file uploads in Laravel applications.
Q) How can I handle and validate different file formats during the upload process in Laravel?
A) You can handle and validate different file formats during the upload process in Laravel by using the mimes rule in the validation rules for the file inputs, specifying the allowed file formats or extensions that you want to validate.
Q) Can I limit the size of each uploaded file when dealing with multiple uploads in Laravel?
A) Yes, you can limit the size of each uploaded file when dealing with multiple uploads in Laravel by setting the max rule with the desired file size limit in the validation rules for the file inputs.
Shahzeb Ahmed
Shahzeb is a Digital Marketer with a Software Engineering background, works as a Community Manager — PHP Community at Cloudways. He is growth ambitious and aims to learn & share information about PHP & Laravel Development through practice and experimentation. He loves to travel and explore new ideas whenever he finds time. Get in touch with him at [email protected]