React Axios Upload Multiple Image Files with Node/Express

File uploading is a primary functionality added in almost every application; we are sure with the help of this tutorial, you can quickly learn about multiple image uploading in React.

In this comprehensive tutorial, we are going to highlight every aspect that is majorly imperative for image file uploading in React.

We have released this step-by-step guide, in which you will learn how to create and install react app, create a reusable component and register in the main component, create an image file uploading API and consume the API using Axios.

You will have thorough knowledge about how to incorporate express API in React application.

Here are the topics that we are covering in this comprehensive tutorial:

  • Set up React project (SQL)
  • Creating reusable component
  • Using Bootstrap to create UI component
  • Building node server to create REST API
  • Consuming file upload API using Axios
  • MongoDB database setup to store uploaded images
  • Testing file upload system

Build Multiple Image Upload in React with Axios and Node

  • Step 1: Download React Project
  • Step 2: Install Bootstrap Package
  • Step 3: Install Axios Package
  • Step 4: Create Image Upload REST API
  • Step 5: Create Image Upload Component
  • Step 6: Register Component in App.js
  • Step 7: Start React Application

Download React Project

The first section shows you how to install the react application; if you are not new to react, ignore this step.

npx create-react-app react-demo-app

Now, step inside the project.

cd react-demo-app

Install Bootstrap Package

Next, add Bootstrap into React using provided command for creating flawless user interface components.

npm install bootstrap

Add bootstrap CSS in the primary src/App.js file, and this allows building a user interface.

import React from 'react';

import '../node_modules/bootstrap/dist/css/bootstrap.min.css';
import './App.css';

class App extends Component {
  render() {
    return (
      <div className="App container mt-5">

      </div>
    );
  }
}

export default App;

Install Axios Package

Axios is an agile library that carries weight, and it’s a prodigy without which you can’t make HTTP requests, so shake a leg and install Axios package into React.

npm install axios

Create Image Upload REST API

In this section, you will get pragmatic approaches on building multiple file upload rest API using node js and express js in the same way you will also ascertain how to store image files in the MongoDB database using the blatant packages.

Here are the instructions to build the Node js backend, hence create node js backend.

Execute command to formulate backend folder and get inside of it.

mkdir backend && cd backend

Next, run the npm initializer command to set up the latest npm package.

npm init

Next, type the following commands to install multer express mongoose cors body-parser and uuid libraries.

npm install multer express mongoose cors body-parser uuid

Let’s automate the server starting process, so add the nodemon package as a development dependency.

npm install nodemon --save-dev

Next, run a command to create a database file where we need to define the database name.

mkdir db && cd db && touch database.js

Open and update the code in the backend/db/database.js file.

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

In the next step, we define the logical structure so create the schema file, first get out from the backend/db folder and run the following command.

mkdir models && cd models && touch File.js

Update code in backend/models/File.js.

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const fileSchema = new Schema({
    _id: mongoose.Schema.Types.ObjectId,
    imagesArray: {
        type: Array
    }
}, {
    collection: 'files'
})

module.exports = mongoose.model('File', fileSchema)

Next, we need to create routes to use the multer to handle file uploads, so execute the following command.

mkdir routes && cd routes && touch file.route.js

Open and add the code in the backend/routes/file.route.js file.

let express = require('express');
let mongoose = require('mongoose');
const { v4: uuidv4 } = require('uuid');
let multer = require('multer');
let router = express.Router();

const DIR = './public/';
let File = require('../models/File');


const storage = multer.diskStorage({
    destination: (req, file, cb) => {
        cb(null, DIR);
    },
    filename: (req, file, cb) => {
        const fileName = file.originalname.toLowerCase().split(' ').join('-');
        cb(null, uuidv4() + '-' + 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('File type not accepted (.png, .jpg, .jpeg)'));
        }
    }
});

router.post('/multi-images-upload', upload.array('imagesArray', 8), (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 File({
        _id: new mongoose.Types.ObjectId(),
        imagesArray: reqFiles
    });

    user.save().then(result => {
        res.status(201).json({
            message: "Uploaded!",
            userCreated: {
                _id: result._id,
                imagesArray: result.imagesArray
            }
        })
    }).catch(err => {
        console.log(err),
            res.status(500).json({
                error: err
            });
    })
})

router.get("/", (req, res, next) => {
    File.find().then(response => {
        res.status(200).json({
            message: "Images fetched!",
            posts: response
        });
    });
});

module.exports = router;

After uploading images, you need to keep them in a public directory, execute the following command.

mkdir public

In the backend folder, create index.js file, this file is the confluence of the settings that starts the node server, open the src/index.js file and update the following code in it.

let express = require('express');
let mongoose = require('mongoose');
let bodyParser = require('body-parser');
let mongo = require('./db/database');
let cors = require('cors');

const REST_API = require('../backend/routes/file.route')

mongoose.Promise = global.Promise;
    mongoose.connect(mongo.db, {
        useUnifiedTopology: true,
        useNewUrlParser: true
    }).then(() => {
        console.log('Database connected')
    },
    err => {
        console.log(err)
    }
)

const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
    extended: true
}));

app.use(cors());

app.use('/public', express.static('public'));
app.use('/endpoint', REST_API)

const port = process.env.PORT || 8000;

app.listen(port, () => {
    console.log('Connected : ' + port)
})

app.use((req, res, next) => {
    setImmediate(() => {
        next(new Error('Error occured'));
    });
});

Create Image Upload Component

This section displays what should be done next. First, create components folder in src and create upload.component.js file in src/components.

Update code in src/components/upload.component.js file.

import React, { Component } from 'react';
import axios from 'axios';

export default class UploadComponent extends Component {

    constructor(props) {
        super(props);

        this.onImgChange = this.onImgChange.bind(this);
        this.onUpload = this.onUpload.bind(this);

        this.state = {
            imagesArray: ''
        }
    }

    onImgChange(event) {
        this.setState(
            { 
                imagesArray: [...this.state.imagesArray, ...event.target.files] 
            }
        )
    }

    onUpload(event) {
        event.preventDefault()
        let formData = new FormData();

        for (const key of Object.keys(this.state.imagesArray)) {
            formData.append('imagesArray', this.state.imagesArray[key])
        }
        axios.post("http://localhost:8000/endpoint/multi-images-upload", formData, {
        }).then(response => {
            console.log((response.data))
        })
    }

    render() {
        return (
            <div>
                <form onSubmit={this.onUpload}>

                    
                    <div className="form-group">
                        <input className="form-control form-control-lg mb-3" type="file" multiple name="imagesArray" onChange={this.onImgChange} />
                    </div>

                    <div className="d-grid">
                        <button className="btn btn-danger" type="submit">Submit</button>
                    </div>
                </form>
            </div>
        )
    }
}

You have to create a simple form with input file and button, set the state first and on files upload, change the state. We are using the form data object to upload the images on the server; we need to predominantly use the REST API that we have built earlier.

Register Component in App Js

We need to let React know that a new component exists that uploads multiple images into the MongoDB database after uploading with utmost nuance.

Consequently register the file upload component in the src/App.js file.

import React, { Component } from 'react';

import '../node_modules/bootstrap/dist/css/bootstrap.min.css';
import './App.css';

import UploadComponent from './components/upload.component';

class App extends Component {
  render() {
    return (
      <div className="App container mt-5">
          <UploadComponent />
      </div>
    );
  }
}

export default App;

Start React Application

You have to start the React app and at the same time the node server.

First, start the app on the browser by executing the npm start command.

npm start

Use the given url to view the app.

http://localhost:3000

In the second step, you have to start the back-end server and the database; make sure to execute the following commands inside the back-end folder.

nodemon server
mongod

Once the node express is running perfectly, after uploading the file, you can see the information of the uploaded file on the following url.

http://localhost:8000/endpoint

React Upload Multiple Images

Conclusion

As a developer, you must know creating an application with an image file uploading feature, it is a mandatory functionality that allows users to upload images and store them in the database. In this guide, we followed some novel approaches to create multiple image file uploading features in React. Bit by bit, we uncovered curtains from the various topics such as creating node backend, creating API with the express, using MongoDB to store data, and using Axios to make an HTTP request to store the uploaded files.

We hope the confluence of various topics enlightened you on some of the most widely used tech stacks in the tech industry. We hope you liked our audacity, and this tutorial will heal the excruciating pain of novice developers.