How to upload files in Vue With Node.js & Express
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 # creating fileupload folder
cd fileupload # changing directory to fileupload
npm init -y # initializing package.json file
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.
const express = require('express');
const fileUpload = require('express-fileupload');
const cors = require('cors')
const app = express();
// middle ware
app.use(express.static('public')); //to access the files in public folder
app.use(cors()); // it enables all cors requests
app.use(fileUpload());
// file upload api
app.post('/upload', (req, res) => {
if (!req.files) {
return res.status(500).send({ msg: "file is not found" })
}
// accessing the file
const myFile = req.files.file;
// mv() method places the file inside public directory
myFile.mv(`${__dirname}/public/${myFile.name}`, function (err) {
if (err) {
console.log(err)
return res.status(500).send({ msg: "Error occured" });
}
// returing the response with file path and name
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.
<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]; // accessing file this.selectedFile = selectedFile;
},
onUploadFile() {
const formData = new FormData();
formData.append("file", this.selectedFile); // appending file
// sending file to the backend
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.
<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.
<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.
<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); // appending file
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.