Image upload and validation using Laravel and VueJs

Jagadesha NH
Feb 20, 2017 · 3 min read

We all know that

An image is worth a thousand words

We find images in almost every application that we use in today’s world. And Laravel being so nice, it supports image uploads out of the box.


However, It’s even more fun if we can upload images via ajax and validate.

So, let’s get started. I assume you already have a new Laravel application running and generated authentication scaffolding (it’s not necessary, but gives us a nice looking view to work with). I am gonna copy content of my home.blade.php in to welcome.blade.php and work on it.

Under your resources/assets/js/components create a file called FileUpload.vue

<div class="row">
<div class="col-md-12">
<div class="col-md-2">
<img :src="image" class="img-responsive">
<div class="col-md-8">
<input type="file" v-on:change="onFileChange" class="form-control">
<div class="col-md-2">
<button class="btn btn-success btn-block" @click="upload">Upload</button>
<style scoped>
max-height: 36px;
export default{
return {
image: ''
methods: {
onFileChange(e) {
let files = || e.dataTransfer.files;
if (!files.length)
createImage(file) {
let reader = new FileReader();
let vm = this;
reader.onload = (e) => {
vm.image =;
upload(){'/api/upload',{image: this.image}).then(response => {


Once we have created FileUpload component let’s register it in app.js


now that we have registered our component, we can use it like


edit your welcome.blade.php, and serve application.


<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-default">
<div class="panel-heading">Upload your favorite image!</div>
<div class="panel-body">

If you now visit localhost:8000 you should have an output like the following.

For uploading image will be making use of image/intervention php library, follow the instruction and install this package.

In our axios post method we are sending image data which is in base64 encoded format back to our server, so let’s create that route.

Route::post('/upload', function (Request $request) {
$validator = Validator::make($request->all(), [
'image' => 'required|image64:jpeg,jpg,png'
if ($validator->fails()) {
return response()->json(['errors'=>$validator->errors()]);
} else {
$imageData = $request->get('image');
$fileName = Carbon::now()->timestamp . '_' . uniqid() . '.' . explode('/', explode(':', substr($imageData, 0, strpos($imageData, ';')))[1])[1];
return response()->json(['error'=>false]);

In the above code, we are using custom validation rule called image64 let’s define our custom validation rule first.

Inside AppServiceProvider under boot function register our custom validation rule as

public function boot()
Validator::extend('image64', function ($attribute, $value, $parameters, $validator) {
$type = explode('/', explode(':', substr($value, 0, strpos($value, ';')))[1])[1];
if (in_array($type, $parameters)) {
return true;
return false;

Validator::replacer('image64', function($message, $attribute, $rule, $parameters) {
return str_replace(':values',join(",",$parameters),$message);

and, one last final step is to register a validation message in validation.php

'image64' => 'The :attribute must be a file of type: :values.','custom' => [
'attribute-name' => [
'rule-name' => 'custom-message',

Final output

Jagadesha NH

Written by

HI THERE! Welcome to my blog. I'm 'Jagadesha NH', passionate programmer, fun-loving web developer living in the 'Silicon Valley of India'.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade