Uploading Image using AJAX

Uploading images is one of the basics of web development. But it is one of the most important parts of the web as well as the app.

Here in this article, we will learn about the process of image upload using AJAX. This method applies from Laravel 5 to the current version of Laravel.

Below we will program a simple that uses AJAX and Laravel for uploading images. We will use jQuery’s AJAX request to add or update images because it helps in uploading without refreshing the page.

Required Contents

  • Routes
  • Blade and JS
  • Controller and Logic

Routes

First of all, we will make two route files, one for returning the view in which we input the image and another for uploading an image.

Route::get('user/profile', 'UserController@getUser')->name('profile');
Route::post('user/profile','UserController@postUpdate')->name('updateProfile');

Blade And JS

After writing routes, make profile.blade.php inside the resource folder.

@extends('app')
@section('content')
    <div class="container">
        <div class="row">
            <div class="col-md-6">
                <h3><i class="fa fa-image"></i> Ajax Image Upload</h3>
                <br>

                <h4>User Profile</h4>
                <hr>
                <div style="display: flex;">
                    <div>
                        <img class="imgPreview img img-circle" 
                         width="80" src="https://via.placeholder.com/80">
                    </div>
                    <div style="margin-left: 15px; flex-grow: 1">
                        <p>Choose a file</p>
                        <input id="photo" type="file">
                        <input type="hidden" name="id" value="{{$user->id}}">
                        <br>
                        <div class="progress">
                            <div class="progress-bar" 
                                 role="progressbar" aria-valuemin="0"
                                 aria-valuemax="100">

                            </div>
                        </div>
                    </div>
                </div>


                <table class="table table-condensed table-bordered">
                    <tr>
                        <td width="100">Name</td>
                        <td>{{$user->name}}</td>
                    </tr>
                    <tr>
                        <td>E-Mail</td>
                        <td>{{$user->email}}</td>
                    </tr>
                    <tr>
                        <td>Phone</td>
                        <td>{{$user->phone}}</td>
                    </tr>
                    <tr>
                        <td>Address</td>
                        <td>{{$user->address}}</td>
                    </tr>
                </table>
            </div>
        </div>
    </div>

    <script>
        $(function () {
            $.ajaxSetup({
                headers: {'X-CSRF-Token': '{{csrf_token()}}'}
            });

            var id = $('input[name="id"]').val();


            $('#photo').change(function () {
                var photo = $(this)[0].files[0];
                var formData = new FormData();
                formData.append('id', id);
                formData.append('photo', photo);

                $.ajax({
                    xhr: function () {
                        var xhr = new window.XMLHttpRequest();
                        xhr.upload.addEventListener("progress", function (evt) {
                            if (evt.lengthComputable) {
                                var percentComplete = evt.loaded / evt.total;
                                percentComplete = parseInt(percentComplete * 100);
                                console.log(percentComplete);
                                $('.progress-bar').css('width', percentComplete + '%');
                                if (percentComplete === 100) {
                                    console.log('completed 100%')

                                    var imageUrl = window.URL.createObjectURL(photo)
                                    $('.imgPreview').attr('src', imageUrl);
                                    setTimeout(function () {
                                        $('.progress-bar').css('width', '0%');
                                    }, 2000)
                                }
                            }
                        }, false);
                        return xhr;
                    },
                    url: '{{route('updateProfile')}}',
                    type: 'POST',
                    data: formData,
                    processData: false,
                    contentType: false,
                    success: function (res) {
                        if(!res.success){alert(res.error)}
                    }
                })
            })
        })
    </script>
@endsection

Controller And Logic

Finally, we develop a controller using php artisan make:controller UserController

<?php
namespace App\Http\Controllers;

use App\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;

class UserController extends Controller
{
    public function getUser()
    {
        $user = User::find(1);
        return view('profile', compact('user'));
    }

    public function postUpdate(Request $request)
    {
    	$validator = Validator::make($request->all(), [
                		'photo' => 'required|image|mimes:png,jpg,jpeg|max:200',
            		]);

        if ($validator->fails()) {
            return response()
                ->json([
                    'success' => false,
                    'error' =>  $validation->errors()->first()
                ]);
        }

        $user = User::find($request->input('id'));

        if ($request->hasFile('photo')) {
            $photo = $request->file('photo');

            $fileName = $user->id . "." . $photo->getClientOriginalExtension();
            $request->file('photo')->move(public_path('user-photos'), $fileName);
            $user->update(['photo' => $fileName]);
        }

        return ['success'=>true,'message'=>'Successfully updated'];
    }
}

There are two methods inside this class which are getUser and postUpdate. getUser method returns the user’s data to the profile view whereas postUpdate validates the photo with the Laravel validator facade and if it passes then it uploads the image.

Image Requirments

  • image having jpg, png, and jpeg as file extension
  • Size having less than 200KB.

We can change the requirements from postUpdate method.

Asmit Nepali, a Full Stack Developer, holds a Software Engineering degree from Gandaki College of Engineering and Science. Proficient in PHP Laravel, Vue.js, MySQL, Tailwind, Figma, and Git, he possesses a robust technical skill set.

Leave a Comment