Vue.js 3 Express: Single & Multiple Files and Images Upload
Let’s get started.
Table of Contents
Set Up Project
Use command to install Vue project:
vue create vue-single-multi-files-upload
Enter inside the project:
cd vue-single-multi-files-upload
Start the app in the browser:
npm run serve
Configure Bootstrap
Open the public/index.html file and add the Bootstrap CDN link.
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh">
Install Axios Library
Install Axios library in Vue.js app to make the API requests.
# NPM
npm install axios --save
# Yarn
yarn add axios
Build Express/Node Server
We will be uploading files and images in the remote server so that we will create a backend server using Node. Create file upload API using Express.js and store it in the MongoDB database.
Create a server folder at the root of your Vue.js project.
mkdir server && cd server
Create package.json for node server.
npm init
We need to install the following dependencies.
npm i --save cors express mongoose multer body-parser
We have to install the nodemon package to re-start the node server.
Define MongoDB Database
Create server/db/database.js file and folder, here we will define the mongoDB database.
module.exports = {
db: 'mongodb://localhost:27017/fileupload'
}
Create Schema
Create server/models folder, create a new file and name it User.js.
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
let userSchema = new Schema({
_id: mongoose.Schema.Types.ObjectId,
files: {
type: Array
},
}, {
collection: 'users'
})
module.exports = mongoose.model('User', userSchema)
Create File Upload API
Create a new folder server/public, and we are going to store uploaded files in this folder.
mkdir public
Next, we need to create a server/routes folder; in this folder, we have to create user.routes.js file. Add all the following code inside the routes file.
let express = require('express'),
multer = require('multer'),
mongoose = require('mongoose'),
router = express.Router();
const DIR = './public/';
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, DIR);
},
filename: (req, file, cb) => {
const fileName = file.originalname.toLowerCase().split(' ').join('-');
cb(null, fileName)
}
});
var upload = multer({
storage: storage,
fileFilter: (req, file, cb) => {
if (file.mimetype == "image/png" || file.mimetype == "image/jpg" || file.mimetype == "image/jpeg") {
cb(null, true);
} else {
cb(null, false);
return cb(new Error('Only .png, .jpg and .jpeg format allowed!'));
}
}
});
// User model
let User = require('../models/User');
router.post('/file-upload', upload.array('files', 10), (req, res, next) => {
const reqFiles = []
const url = req.protocol + '://' + req.get('host')
for (var i = 0; i < req.files.length; i++) {
reqFiles.push(url + '/public/' + req.files[i].filename)
}
const user = new User({
_id: new mongoose.Types.ObjectId(),
files: reqFiles
});
user.save().then(result => {
console.log(result);
res.status(201).json({
message: "Done upload!",
userCreated: {
_id: result._id,
files: result.files
}
})
}).catch(err => {
console.log(err),
res.status(500).json({
error: err
});
})
})
router.get("/", (req, res, next) => {
User.find().then(data => {
res.status(200).json({
message: "Data fetched!",
users: data
});
});
});
module.exports = router;
The Multer package provides the upload.array method. This method takes two parameters, the file name and the total number of files to be uploaded to the server.
You can have a look at the full Multer documentation here.
Set up Node Server
Next, we need to create a server/index.js file. In this file, we define all the server related settings.
let express = require('express'),
mongoose = require('mongoose'),
cors = require('cors'),
bodyParser = require('body-parser'),
dbConfig = require('./db/database');
// Routes to Handle Request
const userRoute = require('../server/routes/user.routes')
// MongoDB Setup
mongoose.Promise = global.Promise;
mongoose.connect(dbConfig.db, {
useNewUrlParser: true,
useUnifiedTopology: true
}).then(() => {
console.log('Database sucessfully connected')
},
error => {
console.log('Database could not be connected: ' + error)
}
)
// Setup Express.js
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: false
}));
app.use(cors());
// Make Images "Uploads" Folder Publicly Available
app.use('/public', express.static('public'));
// API Route
app.use('/api', userRoute)
const port = process.env.PORT || 4000;
const server = app.listen(port, () => {
console.log('Connected to port ' + port)
})
// Error
app.use((req, res, next) => {
// Error goes via `next()` method
setImmediate(() => {
next(new Error('Something went wrong'));
});
});
app.use(function (err, req, res, next) {
console.error(err.message);
if (!err.statusCode) err.statusCode = 500;
res.status(err.statusCode).send(err.message);
});
Run the Express Server
Open the terminal window and run the following command to start the MongoDB database.
mongod --config /usr/local/etc/mongod.conf
brew services start mongodb-community@4.2
mongo
Start the nodemon server:
nodemon index.js
Here are the file upload API we created:
Method | API |
---|---|
GET | http://localhost:4000/api |
POST | http://localhost:4000/api/file-upload |
Create Single & Multiple Files Uploading Component
In this step we will build Single & Multiple Files and Images Uploading component.
First, create a component/fileUpload.vue in Vue app. Then, add the following code inside of it.
<template>
<div>
<div class="container">
<form @submit.prevent="handleSubmit">
<div class="form-group">
<input type="file" @change="uploadFile" multiple>
</div>
<div class="form-group">
<button class="btn btn-success btn-block btn-lg">Upload</button>
</div>
</form>
</div>
</div>
</template>
<script>
import axios from "axios";
export default {
data() {
return {
files: null
};
},
methods: {
uploadFile (event) {
this.files = event.target.files
},
handleSubmit() {
const formData = new FormData();
for (const i of Object.keys(this.files)) {
formData.append('files', this.files[i])
}
axios.post('http://localhost:4000/api/file-upload', formData, {
}).then((res) => {
console.log(res)
})
}
}
}
</script>
<style scoped lang="scss">
.container {
max-width: 600px;
}
</style>
The axios.post() method takes the file uploading API that we created using Express.js; the second parameter is the form data that we are sending to the server in multi-parts.
The Object.keys()
method returns an array of a given object’s enumerable property names, here we are extracting the files from the FileList API by iterating in the same order that a standard loop does.
Summary
So this was it, in this tutorial, we have learned how to upload files to the express server using Axios and FormData() web API. I hope you loved this articles. Don’t forget to share it with others.
You can download the complete code of this tutorial here.