Laravel 6 Image/File Upload Validation Example Tutorial

Laravel 6 Image/File Upload Validation Example Tutorial

In this tutorial, you will learn an easy way to upload the files into your server with your laravel 6 application.

Table of Contents

  • List All Documents
  • Add New Document
  • Edit/Update Document
  • Delete/Destroy Document
  • File Validation

File uploads is very basic functionality which require in almost all web-applications. It includes various file types like Images, PDFs, etc. In this tutorial i will show you how to upload Image/File with validation in laravel 6. We will also see file validations as well.

Lets start file upload tutorial in laravel 6 by installing fresh laravel using below command.

composer create-project --prefer-dist laravel/laravel laravel-file-upload

Now update database credentials in .env file.

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=lara-file
DB_USERNAME=root
DB_PASSWORD=

Next, start server using below command.

php artisan serve

In this tutorial, we will make simple form which upload any document such as ImagePDFDoc etc. and list them out.

Lets create document migration using below artisan migration command.

php artisan make:migration create_documents_table

This command will generate document migration file under database/migrations directory. Open document migration file and add two fields title and file_url as shown below.

20190913_150436_create_documents_table.php

<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateDocumentsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('documents', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('title');
            $table->string('file_url')->nullable();
            $table->timestamps();
        });
    }
    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('documents');
    }
}

Next, lets make a document model file using below artisan command.

php artisan make:model Document

This command will generate document model file Document.php under app/ directory. Open Document.php file and add table fields for mass assignable.

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Document extends Model
{
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = ['title', 'file_url'];
}

Next create document controller using below artisan command.

php artisan make:controller DocumentController --resource

This command will create DocumentController.php file under app/Http/Controllers directory as shown below. The controller will contain a method for each of the available resource operations. Resource operations like CRUD (CREATE, READ, UPDATE and DELETE).

DocumentController.php

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class DocumentController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        //
    }
    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        //
    }
    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        //
    }
    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        //
    }
    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function edit($id)
    {
        //
    }
    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, $id)
    {
        //
    }
    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        //
    }
}

This is default DocumentController with resource route methods generated by make:controller artisan command. We can easily create CRUD using this controller.

Next, we will add route in web.php file. Open routes/web.php file and add document routes as shown below.

web.php

<?php
/*
|--------------------------------------------------------------------------
| 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('/', function () {
    return redirect('document');
});
Route::resource('document', 'DocumentController');
Route::post('update-document/{id}', ['as' => 'update-document', 'uses' => '[email protected]']);

Let me explain routes here.

  • First route is responsible to redirect on document route, because we haven’t anything on homepage ‘/’ to display users.
  • Second route is Resource route which is responsible for CREATE, READ, UPDATE and DELETE operation for document.

Third route is responsible for document update operation as we have to deal with file and PUT HTTP method has some bad experience to upload file.

_________________________________________________________________________________

You may also like: Tutorial Laravel 6 with Docker and Docker-Compose

__________________________________________________________________________________

List All Documents

To list all the documents, lest use index method of controller and display data in index.blade.php layout file.

DocumentController.php

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Document;
class DocumentController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $docs = Document::all();
        return view('document.index', ['docs' => $docs]);
    }
    // Other Methods

}

index.blade.php [Layout File]

index.blade.php layout file is responsible to display all document in list view. It extends main layout file layout.blade.php

@extends('layout')

@section('content') <div class="control-btn float-right"> <a href="{{ route('document.create') }}" class="btn btn-primary">Add File</a> </div> <div class="title"> <h1>Documents</h1> </div> @if (session('success')) <div class="alert alert-success" role="alert"> {{ session('success') }} </div> @endif @if (session('error')) <div class="alert alert-danger" role="alert"> {{ session('error') }} </div> @endif <table class="table table-bordered"> <thead> <tr> <th>Title</th> <th>File Name</th> <th>Actions</th> </tr> </thead> <tbody> @forelse ($docs as $doc) <tr> <td>{{ $doc->title }}</td> <td>{{ $doc->file_url }}</td> <td> <div class="action_btn"> <div class="action_btn"> <a href="{{ route('document.edit', $doc->id)}}" class="btn btn-warning btn-sm">Edit</a> </div> <div class="action_btn margin-left-10"> <form action="{{ route('document.destroy', $doc->id)}}" method="post"> @csrf @method('DELETE') <button class="btn btn-danger btn-sm" type="submit">Delete</button> </form> </div> </div> </td> </tr> @empty <tr> <td colspan="3"> <center> No data found </center> </td> </tr> @endforelse </tbody> </table> @endsection

DocumentController.php

/**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     /
    public function create()
    {
        return view('document.add');
    }
    /*
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $reqData = $request->input();
        if ($request->hasFile('file')) {
            $file = $request->file('file');
            $name = time() . rand(11111, 99999) . '.' . $file->getClientOriginalExtension();
            $destinationPath = public_path('docs');
            $file->move($destinationPath, $name);
            $reqData['file_url'] = $name;
        }
        $newFile = Document::create($reqData);
        if ($newFile) {
            $request->session()->flash('success', 'Data successfully added');
        } else {
            $request->session()->flash('error', 'Data successfully added');
        }
        return redirect('document');
    }

add.blade.php

This layout file contain code for rendering add document form. This is located in resources/views/document/ directory.

@extends('layout')
@section('content')
<div class="title">
  <h1>Add Document</h1>
</div>
<form action="{{ route('document.store') }}" method="POST" enctype="multipart/form-data">
  <div class="form-group">
    <label for="title">Title:</label>
    <input type="text" class="form-control" id="title" name="title">
  </div>
  <div class="form-group">
    <label for="file">Choose File:</label>
    <input type="file" class="form-control-file" id="file" name="file">
  </div>
  @csrf
  <button type="submit" class="btn btn-primary">Submit</button>
  <a href="{{ route('document.index') }}" class="btn btn-danger">Back</a>
</form>
@endsection

Edit/Update Document

To update any document, we will use edit and update method from DocumentController.php file. Here edit method stands for render document form with data and update method will manipulate with submitted data.

DocumentController.php

/

  • Show the form for editing the specified resource.

  • @param int $id

  • @return \Illuminate\Http\Response

  • / public function edit($id) { $doc = Document::find($id); if ($doc) {

      return view('document.edit', [ 'doc' =&gt; $doc ]);

    } else {

      return redirect('document')-&gt;with('error', 'File not found');

    } } /**

  • Update the specified resource in storage.

  • @param \Illuminate\Http\Request $request

  • @param int $id

  • @return \Illuminate\Http\Response

  • / public function update(Request $request, $id) { $document = Document::find($id); if (!$document) {

      return redirect('document')-&gt;with('error', 'Data not found');

    } if ($document->file_url == null) {

      $oldImage = '';

    } else {

      $oldImage = $document-&gt;file_url;

    } $updateData = $request->input(); // Supplier Image if ($request->hasFile('file')) {

      $file = $request-&gt;file('file');
      $name = time() . rand(11111, 99999) . '.' . $file-&gt;getClientOriginalExtension();
      $destinationPath = public_path('docs/');
      $file-&gt;move($destinationPath, $name);
      $updateData['file_url'] = $name;            
    
      // Delete Old supplier_image
      if (!empty($oldImage)) {
          if (\File::exists(public_path('docs/' . $oldImage))) {
              \File::delete(public_path('docs/' . $oldImage));
          }
      }

    } $docStatus = $document->update($updateData); if ($docStatus) {

      return redirect('document')-&gt;with('success', 'Data successfully updated.');

    } else {

      return redirect()-&gt;route('document.edit', ['id' =&gt; 1])-&gt;with('error', 'Oops something went wrong. Please try again.');

    } }

In update method, if user submit new file then it will automatically deleted old file and update new file. So it will not create bunch of file in the public/docs directory and require more space.

Here we will create edit.blade.php file for rendering document form with data. See the code below.

edit.blade.php

@extends('layout')
@section('content')
<div class="title">
<h1>Edit Document</h1>
</div>
<form action="{{ route('update-document', ['id' => $doc->id]) }}" method="POST" enctype="multipart/form-data">
<div class="form-group">
  <label for="title">Title:</label>
  <input type="text" class="form-control" id="title" name="title" value="{{ $doc->title }}">
</div>
<div class="form-group">
  <label for="file">Choose File:</label>
  <input type="file" class="form-control-file" id="file" name="file">
</div>
<div class="form-group">
  <img src="/docs/{{ $doc->file_url }}" width="150" height="150">
</div>
@csrf
{{-- @method('PUT') --}}
<button type="submit" class="btn btn-primary">Submit</button>
<a href="{{ route('document.index') }}" class="btn btn-danger">Back</a>
</form>
@endsection

Delete/Destroy Document

To delete document, we will use destroy method of DocumentController.php file. It will delete database records using $document->delete() and also delete document file from public/docs directory.

DocumentController.php

/**

  • Remove the specified resource from storage.

  • @param int $id

  • @return \Illuminate\Http\Response

  • / public function destroy($id) { $document = Document::find($id); if (!$document) {

      $respStatus = 'error';
      $respMsg = 'Data not found';

    } // Delete file $fileUrl = $document->file_url; if (\File::exists(public_path('docs/'.$fileUrl))) {

      \File::delete(public_path('docs/'.$fileUrl));

    } // Delete document from database $isDocDeleted = $document->delete(); if ($isDocDeleted) {

      $respStatus = 'success';
      $respMsg = 'Data deleted successfully';

    } return redirect('document')->with($respStatus, $respMsg); }

  • After successfully deleted operation, it will redirect to document listing page with appropriate response message.

    Awesome. We have completed basic CRUD in our document app.

    File Validation

    File validation is necessary to get rid of unwanted file extensions. Here we will do validations of image and pdf file extensions. For images we will allow only jpg,jpeg and png. We will also validate file size till 10000 kb.

    Lets add validation code in store and update method.

    /**

  • Store a newly created resource in storage.

  • @param \Illuminate\Http\Request $request

  • @return \Illuminate\Http\Response

  • / public function store(Request $request) { // Validate request data $validatedData = $request->validate([

      'title' =&gt; 'required|max:255',
      'file' =&gt; 'required|max:10000|mimes:png,jpeg,jpg,pdf',

    ]); ... // store validated document } /**

  • Update the specified resource in storage.

  • @param \Illuminate\Http\Request $request

  • @param int $id

  • @return \Illuminate\Http\Response

  • / public function update(Request $request, $id) { // Validate request data $validatedData = $request->validate([

      'title' =&gt; 'required|max:255',
      'file' =&gt; 'required|max:10000|mimes:png,jpeg,jpg,pdf',

    ]); ... // update validated document }

  • We can also validate doc and docx extension by adding them in validation mimes.

    'file' => 'required|max:10000|mimes:png,jpeg,jpg,pdf,doc,docx',
    

    This tutorial is on github. You can download code this tutorial from here.

    I hope that you enjoyed this tutorial on file/image upload with validation in laravel 6. Let me know if you have any issue regarding this tutorial. Please do share with your friends. Thank you guys.

    Further Reading

    How to Laravel 6 Database Migrations - Add Admin Role to Users

    A simple Laravel 5 and laravel 6 library that allows you to implement Repository Pattern with a single command

    Laravel 6 Release New Features and Upgrade

    Originally published by Chintan Panchal at codeandtuts.com on September 15, 2019

    =========================

    Thanks for reading :heart: If you liked this post, share it with all of your programming buddies! Follow me on Facebook | Twitter



    laravel php web-development

    Bootstrap 5 Complete Course with Examples

    Bootstrap 5 Tutorial - Bootstrap 5 Crash Course for Beginners

    Nest.JS Tutorial for Beginners

    Hello Vue 3: A First Look at Vue 3 and the Composition API

    Building a simple Applications with Vue 3

    Deno Crash Course: Explore Deno and Create a full REST API with Deno

    How to Build a Real-time Chat App with Deno and WebSockets

    Convert HTML to Markdown Online

    HTML entity encoder decoder Online

    PHP Web Application Development Company

    As a top **PHP Web Application Development Company in USA**[https://www.dataeximit.com/php-development-services/](https://www.dataeximit.com/php-development-services/ "https://www.dataeximit.com/php-development-services/"), we at Data EximIT have...

    PHP Website Development

    Skenix Infotech is a leading PHP Web Development Company that helps companies get results with industry best practices. Get affordable PHP Development Services.

    Laravel Development Company

    Skenix Infotech is a top Laravel Website Development Company with Expert Laravel Developers that provides robust Laravel Development Services at fair costs.

    Hire Dedicated PHP Developer

    Looking to hire affordable yet experienced PHP developers? **[Hire Dedicated PHP Developer](https://hourlydeveloper.io/hire-dedicated-php-developer/ "Hire Dedicated PHP Developer")**, who can convert your idea to reality, within the stipulated...

    Hire PHP Developer

    Looking to develop a PHP based website from scratch or revamp your existing website? **[HourlyDeveloper.io](https://hourlydeveloper.io/ "HourlyDeveloper.io")** has always been an industry leader for companies and business owners looking to hire...