We will use Laravel as a backend and Vue js as a frontend framework or library.
Steps to upload file in Laravel Vue
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.
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 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 the 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 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>
Okay, now 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>
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.
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"
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.
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.
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