X
    Categories: Learn Laravel Tutorials, Tips And Guides
Reading Time: 6 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');

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 >

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

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

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