AppDividend
Latest Code Tutorials

Vue Laravel File Upload | Upload Image in Laravel Vue

4

We will use Laravel as a backend and Vue js as a frontend framework or library. In this small project, we will upload an image from the vue component. First, we download the Laravel and then install the dependencies using pm, and then we will start our project.

Steps to upload file in Laravel Vue

The first step will be to install and configure the Laravel Framework.

Step 1: Install Laravel

Go to your terminal and hit the following command.

composer create-project laravel/laravel vuefileupload --prefer-dist

After installation, go to the project folder root and type the following command.

npm install

It installs all the necessary dependencies to build Vue components.

Step 2: Configure the database.

Add your database credentials in the .env file.

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=vueupload
DB_USERNAME=root
DB_PASSWORD=

Step 3: Create a model and migration files.

To create both the files, insert the following command.

php artisan make:model FileUpload -m

It generates both model and migration files.

Step 4: Define the schema in the migration file.

Go to the create_file_uploads_table.php file and add the schema to it.

Schema::create('file_uploads', function (Blueprint $table) {
   $table->increments('id');
   $table->string('image_name');
   $table->timestamps();
});

Now, migrate the table into the database.

php artisan migrate

Step 5: Define the routes in the web.php file.

Define the following route in the web.php file.

Route::post('/image/store', 'ImageController@store');

Also, create an ImageController.php file via the following command.

 php artisan make:controller ImageController

In that file, define the store function.

<?php

namespace App\Http\Controllers;
use App\FileUpload;

use Illuminate\Http\Request;

class ImageController extends Controller
{
    public function store(Request $request)
    {

    }
}

Step 6: Create a Vue component to upload a file.

Go to the resources  >>  assets  >>  js  >>  components  folder and create a new file called ImageuploadComponent.vue.

// ImageuploadComponent.vue

<template>
    <div class="container" id="app">
        <div class="row justify-content-center">
            <div class="col-md-8">
                <div class="card card-default">
                    <div class="card-header">File Upload Component</div>
                    <div class="card-body">
                        We need to write here file upload HTML code.
                    </div>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
    export default {
        
    }
</script>

Okay, so we have created a new component. Next step is to register that component into the resources  >>  assets  >>  js  >>  app.js file.

// app.js


/**
 * First we will load all of this project's JavaScript dependencies which
 * includes Vue and other libraries. It is a great starting point when
 * building robust, powerful web applications using Vue and Laravel.
 */

require('./bootstrap');

window.Vue = require('vue');

/**
 * Next, we will create a fresh Vue application instance and attach it to
 * the page. Then, you may begin adding components to this application
 * or customize the JavaScript scaffolding to fit your unique needs.
 */

Vue.component('image-component', require('./components/ImageuploadComponent.vue'));

const app = new Vue({
    el: '#app'
});

I have removed the example component from this file because we do not need that anymore.

Step 7: Compile the app.js file code.

We have created the component, but that changes are not still reflected in public  >>  js  >>  app.js file. So need to recompile our code. Go to the CMD and hit the following command.

npm run dev

It generates an app.js file in public  >>  js folder. Now, include this component into the welcome.blade.php file.

<!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>File Upload Tutorial</title>
        <link href="https://fonts.googleapis.com/css?family=Raleway:100,600" rel="stylesheet" type="text/css">
        <link href="{{ asset('css/app.css') }}" rel="stylesheet"/>
    </head>
    <body>
        <div class="container" id="app">
            <image-component></image-component>
        </div>
    <script>
       window.Laravel = <?php echo json_encode([
           'csrfToken' => csrf_token(),
        ]); ?>
    </script>
    <script src="{{asset('js/app.js')}}"></script>
    </body>
</html>

Okay, now start the Laravel development server by the following command.

php artisan serve

Switch to the following URL.

http://localhost:8000

See the below image.

Vue File Upload Tutorial

Step 8: Create a form to upload an image.

In the ImageuploadComponent.vue file, write the following code into it.

// ImageuploadComponent.vue

<template>
    <div class="container">
        <div class="row justify-content-center">
            <div class="col-md-8">
                <div class="card card-default">
                    <div class="card-header">File Upload Component</div>
                    <div class="card-body">
                       <div class="row">
                          <div class="col-md-9">
                              <input type="file" v-on:change="onImageChange" class="form-control">
                          </div>
                          <div class="col-md-3">
                             <button class="btn btn-success btn-block" @click="uploadImage">Upload Image</button>
                          </div>
                       </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
    export default {
        
    }
</script>

In this component, we have used an event and function, which we have not defined yet, so let us do that first.

// ImageuploadComponent.vue

<template>
    <div class="container">
        <div class="row justify-content-center">
            <div class="col-md-8">
                <div class="card card-default">
                    <div class="card-header">File Upload Component</div>
                    <div class="card-body">
                       <div class="row">
                          <div class="col-md-3" v-if="image">
                              <img :src="image" class="img-responsive" height="70" width="90">
                           </div>
                          <div class="col-md-6">
                              <input type="file" v-on:change="onImageChange" class="form-control">
                          </div>
                          <div class="col-md-3">
                             <button class="btn btn-success btn-block" @click="uploadImage">Upload Image</button>
                          </div>
                       </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
    export default {
        data(){
            return {
                image: ''
            }
        },
        methods: {
            onImageChange(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);
            },
            uploadImage(){
                axios.post('/image/store',{image: this.image}).then(response => {
                   console.log(response);
                });
            }
        }
    }
</script>

So, first, we have taken one property called an image. Then we have used the onChange event to track the new image we have browsed. Then that image is displayed on the side div. If the image is null, then it will not show until we browser any image. So we have used v-if conditionals.

Note: We are sending the base 64 binary to the server. So we need to make an image from that. For that, we will use the Image intervention package to do that, so let us first install that.

Step 9: Install the image/intervention package.

Go to your terminal and type the following command to install the intervention/image package.

composer require intervention/image

After installing the package, we need to configure it into the Laravel. So first, go to the config  >>  app.php file and register the Intervention Image Provider.

// app.php

'providers' => [
 Intervention\Image\ImageServiceProvider::class,
];

'aliases' => [
 'Image' => Intervention\Image\Facades\Image::class,
]

After this step, we need to publish the package by the following command.

 php artisan vendor:publish --provider="Intervention\Image\ImageServiceProviderLaravel5"

Now, we can use this package in our ImageController.php file.

Step 10: Code the store function.

Write the following code into the ImageController.php file.

// ImageController.php

    public function store(Request $request)
    {
       if($request->get('image'))
       {
          $image = $request->get('image');
          $name = time().'.' . explode('/', explode(':', substr($image, 0, strpos($image, ';')))[1])[1];
          \Image::make($request->get('image'))->save(public_path('images/').$name);
        }

       $image= new FileUpload();
       $image->image_name = $name;
       $image->save();

       return response()->json(['success' => 'You have successfully uploaded an image'], 200);
     }

Step 11: Finishing our project.

Our UI looks like this.

Laravel Vue Image Upload Tutorial

Our final ImageuploadComponent.vue file looks like this.

// ImageuploadComponent.vue

<template>
    <div class="container">
        <div class="row justify-content-center">
            <div class="col-md-8">
                <div class="card card-default">
                    <div class="card-header">File Upload Component</div>
                    <div class="card-body">
                       <div class="row">
                          <div class="col-md-3" v-if="image">
                              <img :src="image" class="img-responsive" height="70" width="90">
                           </div>
                          <div class="col-md-6">
                              <input type="file" v-on:change="onImageChange" class="form-control">
                          </div>
                          <div class="col-md-3">
                             <button class="btn btn-success btn-block" @click="uploadImage">Upload Image</button>
                          </div>
                       </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
    export default {
        data(){
            return {
                image: ''
            }
        },
        methods: {
            onImageChange(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);
            },
            uploadImage(){
                axios.post('/image/store',{image: this.image}).then(response => {
                   if (response.data.success) {
                     alert(response.data.success);
                   }
                });
            }
        }
    }
</script>

So, finally, our Vue Laravel File Upload example is over. I have already put the above code on Github. You can check it out.

Fork Me On Github

 

 

4 Comments
  1. mimie says

    hi,

    i got this error when upload file:

    “message”: “Can’t write image data to path (C:\\xampp\\htdocs\\vue-app\\public\\images/1521536190.jpeg)”,
    “exception”: “Intervention\\Image\\Exception\\NotWritableException”,
    “file”: “C:\\xampp\\htdocs\\vue-app\\vendor\\intervention\\image\\src\\Intervention\\Image\\Image.php”,
    “line”: 143,
    “trace”: [
    {
    “file”: “C:\\xampp\\htdocs\\vue-app\\app\\Http\\Controllers\\ImageController.php”,
    “line”: 16,
    “function”: “save”,
    “class”: “Intervention\\Image\\Image”,
    “type”: “->”
    },

    1. Moses Adetola says

      Check that you have public/images directory.

  2. navid says

    hi,
    thank you about pulish this article, but have question please, you use vm instance and set image data but this value just have value in inner scope and actuly after this scope {vm.image = …} image get default value empty

    can you choose better way to set vm.image globaly not locally?

  3. Omar Morales says

    what can i do if i want to upload word or pdf files? because this only works with images right?

Leave A Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.