In this tutorial, we are going to learn about how to upload the files in vue.js using express as a backend API.

Creating Express Backend server

We are creating a post API using NodeJS & express, which helps us to upload the files like (images, pdf, etc) to the backend server.

Setup the backend project

Let’s set up the node.js backend project by running the following commands one by one in your terminal.

mkdir fileupload cd fileupload npm init -y

Installing packages

Now, we need to install four packages which are express , express-fileupload , cors and nodemon .

Run the below command to install the packages.

npm i express express-fileupload cors nodemon

Now open the fileupload folder in your favorite code editor and create a new file called server.js .

Add the following code to the server.js file.

server.js

const express = require ( 'express' ) ; const fileUpload = require ( 'express-fileupload' ) ; const cors = require ( 'cors' ) const app = express ( ) ; app . use ( express . static ( 'public' ) ) ; app . use ( cors ( ) ) ; app . use ( fileUpload ( ) ) ; app . post ( '/upload' , ( req , res ) => { if ( ! req . files ) { return res . status ( 500 ) . send ( { msg : "file is not found" } ) } const myFile = req . files . file ; myFile . mv ( ` ${ __dirname } /public/ ${ myFile . name } ` , function ( err ) { if ( err ) { console . log ( err ) return res . status ( 500 ) . send ( { msg : "Error occured" } ) ; } return res . send ( { name : myFile . name , path : ` / ${ myFile . name } ` } ) ; } ) ; } ) app . listen ( 4500 , ( ) => { console . log ( 'server is running at port 4500' ) ; } )

In the above code, we first imported three packages which are express , express-fileupload and cors , next we created express application by invoking express() function.

Our post API route is /upload .

We are placing files inside the public folder, so that we need to create a public folder inside our backend project.

Adding scripts

To run and restarting the backend server we are using the nodemon , open your package.json file and add the following code to scripts object.

"server" : "nodemon server.js"

Now, start the backend server by running npm start server command in your terminal.which shows a similar text.

nodemon server.js [ nodemon ] 1.14 .3 [ nodemon ] to restart at any time, enter ` rs ` [ nodemon ] watching: *.* [ nodemon ] starting ` node server.js ` server is running at port 4500

Creating a Vue Project

Let’s create a new vue project by using the Vue Cli.

vue create vue-file-upload

This above command will create a new vue project inside the vue-file-upload folder.

Now, change your current working directory to vue-file-upload by running the following command.

cd vue-file-upload

Installing Axios Library

We are installing the axios http client library in vue project, which helps us to make the post request to our backend API.

npm i axios

Creating file upload component

Now, open the vue-file-upload folder in your favorite code editor and create a new file called FileUpload.js inside the components folder.

Add the following code to the FileUpload.js file.

FileUpload.vue

< template > < div class = " file-upload " > < input type = " file " @change = " onFileChange " /> < button @click = " onUploadFile " class = " upload-button " :disabled = " !this.selectedFile " > Upload file </ button > </ div > </ template > < script > import axios from "axios" ; export default { data ( ) { return { selectedFile : "" , } ; } , methods : { onFileChange ( e ) { const selectedFile = e . target . files [ 0 ] ; this . selectedFile = selectedFile ; } , onUploadFile ( ) { const formData = new FormData ( ) ; formData . append ( "file" , this . selectedFile ) ; axios . post ( "http://localhost:4500/upload" , formData ) . then ( res => { console . log ( res ) ; } ) . catch ( err => { console . log ( err ) ; } ) ; } } } ; </ script >

In the above code, we have added two elements inside the template which are input and button . where attribute type=file is added to the input element so that it can accept the files.

Inside the methods object we have defined two methods which are onFileChange() and onUploadFile() .

The onFileChange() method is invoked once a user is selected the file , inside that method we are accessing the file data using e.target.files[0] and setting it to this.selectedFile data property.

The onUploadFile() is invoked once a user clicks the Upload File button, inside that method, we are creating a new FormData object by invoking the FormData constructor and appending the file to formdata using append() method.

Then we are uploading a file to the backend api using the axios.post() method by passing API endpoint and formData as arguments.

Adding styles to FileUpload component

Add the below styles to the FileUpload.vue file.

FileUpload.vue

<style scoped> .file-upload { box-shadow : 2px 2px 9px 2px #ccc ; border-radius : 1rem ; padding : 2rem ; display : flex ; flex-direction : column ; justify-content : space-between ; font-size : 1rem ; width : 60% ; margin : 0 auto ; } input { font-size : 0.9rem ; } input, div, button { margin-top : 2rem ; } .upload-button { width : 7rem ; padding : 0.5rem ; background-color : #278be9 ; color : #fff ; font-size : 1rem ; font-weight : 500 ; cursor : pointer ; border-radius : 1rem ; } .upload-button:disabled { background-color : #b3bcc4 ; cursor : no-drop ; }

Now, import the FileUpload component inside the App.vue file.

App.vue

< template > < div id = " app " > < FileUpload /> </ div > </ template > < script > import FileUpload from "./components/FileUpload.vue" ; export default { name : "app" , components : { FileUpload } } ; </ script >

Start the Vue app development server by running the following command in your terminal.

npm run serve

Testing file upload component

Let’s test the FileUpload component by uploading a sample image or file.

Note: Make sure that your backend server is running.

Have you seen in the above image, our file is successfully uploaded to the backend server.

Adding a progress bar

Let’s add the progress bar to our FileUpload component so that the user knows how much amount of file is uploaded.

The axios.post() method also accepts a third argument, which is an object that contains an onUploadProgress() method by using that we can add a progress bar to the FileUpload component.

update the FileUpload.vue file with the below code.

FileUpload.vue

< template > < div class = " file-upload " > < input type = " file " @change = " onFileChange " /> < div v-if = " progress " class = " progess-bar " : style =" { 'width' : progress } " > {{progress}} </ div > < button @click = " onUploadFile " class = " upload-button " :disabled = " !this.selectedFile " > Upload file </ button > </ div > </ template > < script > import axios from "axios" ; export default { data ( ) { return { selectedFile : "" , progress : 0 } ; } , methods : { onFileChange ( e ) { const selectedFile = e . target . files [ 0 ] ; this . selectedFile = selectedFile ; this . progress = 0 ; } , onUploadFile ( ) { const formData = new FormData ( ) ; formData . append ( "file" , this . selectedFile ) ; axios . post ( "http://localhost:4500/upload" , formData , { onUploadProgress : ProgressEvent => { let progress = Math . round ( ( ProgressEvent . loaded / ProgressEvent . total ) * 100 ) + "%" ; this . progress = progress ; } } ) . then ( res => { console . log ( res ) ; } ) . catch ( err => { console . log ( err ) ; } ) ; } } } ; </ script >

You can also improve it more like hiding the upload button during the file is uploading or getting the file url once a file is uploaded to the server, etc.

Code repositories