Vue 2 Express- Learn To Upload Single & Multiple Files And Images Using Express.js API

In this Vue 2 tutorial, we will get to learn how to upload Single & Multiple files and images to the Node Server from Vue application using Express.js API.

In addition, we will be learning how to send Multipart Form data using FormData() Web API.

 

Now, let’s see how to do so step by step:

 

Step 1- Set Up Vue Project

Step 2- Configure The Bootstrap

Step 3- Install Axios Library

Step 4- Build Express/Node Server

Step 5- Create File Upload API

Step 6- Set Up Node server

Step 7- Run The Express Server

Step 8- Create Files Uploading Component

Step 9- Conclusion

 

Step 1- Set Up Vue Project

First of all, we have to use the given command in order to install the Vue project:

vue create vue-single-multi-files-upload

Next, we have to enter inside the project:

cd vue-single-multi-files-upload

 

To remove the multi-word error warning, we need to add the below code to the vue.config.js file:

const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  transpileDependencies: true,
  lintOnSave: false,
})

 

Error: digital envelope routines::unsupported
opensslErrorStack: [ 'error:03000086:digital envelope routines::initialization error' ],
library: 'digital envelope routines',
reason: 'unsupported',
code: 'ERR_OSSL_EVP_UNSUPPORTED'

 

To remove the above error for invoking the app, do remember to update the “scripts”: [] array in the package.json file.

"scripts": {
    "serve": "export NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service serve",
    "build": "export NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service build",
    "lint": "export NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service lint"
},

 

Then, we run the given command to start the Vue app on the browser

npm run serve

 

Step 2- Configure The Bootstrap

In this step, we will 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">

 

Step 3- Install Axios Library

Here, we will install the Axios library in the Vue.js app to make the API requests:

# NPM
npm install axios --save

# Yarn
yarn add axios

 

Step 4- Build Express/Node Server

We will be uploading files and images to the remote server so that we will create a backend server using Node. Then, we have to create a file upload API using Express.js and store it in the MongoDB database.

Next, we will create a server folder at the root of our Vue.js project:

mkdir server && cd server

Further, we have to create package.json for the Node server:

npm init

Afterward, we need to install the following dependencies:

npm i --save cors express mongoose multer body-parser

 

Then, we have to install the nodemon package to re-start the Node server:

 

Define MongoDB Database

Here, we will create the server/db/database.js file and folder and we will define the MongoDB database:

module.exports = {
  db: 'mongodb://localhost:27017/fileupload'
}

 

Create Schema

Then, we have to create the server/models folder after which we create a new file named 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)

 

Step 5- Create File Upload API

In this step, we have to 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 where we have to create the user.routes.js file. Then, we will add the given 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.

 

Step 6- Set Up Node Server

Further, 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
  .connect('mongodb://127.0.0.1:27017/mydatabase')
  .then((x) => {
    console.log(`Connected to Mongo! Database name: "${x.connections[0].name}"`)
  })
  .catch((err) => {
    console.error('Error connecting to mongo', err.reason)
  })
// 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);
});

 

Step 7- Run the Express Server

In this step, we will open the terminal window and run the following command to start the MongoDB database:

mongo

Then, we start the nodemon server:

nodemon

 

Here is the file upload API we created:

We have created the File Uploading API using Node and Express.js. Now, let us test out our newly built API using Postmen:

vue node express file upload example

 

Method API
GET http://localhost:4000/api
POST http://localhost:4000/api/file-upload

 

Step 8- Create Single & Multiple Files Uploading Component

In this step, we will build Single & Multiple Files and Images Uploading Component.

Firstly, we will create a component/fileUpload.vue in the Vue app. Then, we add the following code inside 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.

Create Single & Multiple Files Uploading Component

 

Step 9- Conclusion

So, in this tutorial, we have seen how to upload files to the express server using Axios and FormData() web API.

 

Thanks

Leave a Reply

Your email address will not be published. Required fields are marked *