Here are the steps to upload a file using Laravel and Vue.js.
Step 1: Install Laravel
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 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(); });
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');
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>
We have created a new component. The 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' });
e removed the example component from this file because we no longer need that.
Step 7: Compile the app.js file code.
We created the component, but the changes are still not reflected in the public>> js >> app.js file. So we need to recompile our code. Go to the CMD and hit the following command.
npm run dev
It generates an app.js file in the public>> js folder. Now, include this component in 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>
Start the Laravel development server with the following command.
php artisan serve
Switch to the following URL.
http://localhost:8000
See the below image.
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>
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 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"
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: Finish our project.
Our UI looks like this.
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>
You can check it out!

Krunal Lathiya is a seasoned Computer Science expert with over eight years in the tech industry. He boasts deep knowledge in Data Science and Machine Learning. Versed in Python, JavaScript, PHP, R, and Golang. Skilled in frameworks like Angular and React and platforms such as Node.js. His expertise spans both front-end and back-end development. His proficiency in the Python language stands as a testament to his versatility and commitment to the craft.
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”: “->”
},
Check that you have public/images directory.
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?
what can i do if i want to upload word or pdf files? because this only works with images right?
i have a problem