Image upload and validation using Laravel and VueJs

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.

$request->file('image')->store('images');

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

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

});
}
}
}
</script>

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

Vue.component('file-upload',require('./components/FileUpload.vue'));

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

<file-upload></file-upload>

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

@extends('layouts.app')

@section('content')
<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">
<file-upload></file-upload>
</div>
</div>
</div>
</div>
</div>
@endsection

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];
Image::make($request->get('image'))->save(public_path('images/').$fileName);
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

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.