Uploading multiple files to Express.js backend from React.js frontend using REST API

Uploading multiple files to Express.js backend from React.js frontend using REST API

Hi, there!

Today I will discuss how to upload files in the Express.js app. We will use the multer package for uploading files. With multer, we can upload a single file or multiple files. Let's jump into our program.

Backend

First of all, we will create our backend. I assume that you have node.js and npm already installed on your computer. So, create a new folder named multer-practice

Open the terminal inside the folder and run the following command

npm init -y
npm install express bodyparser multer nodemon

In the first line, we initialized a node.js project with the default values. On the other line we installed express.js, bodyparser, multer and nodemon.

Now, open the directory inside VS Code. You can prefer your favourite code editor or IDE.

In the package.json file add the following codes in the scripts object.

"start": "node server.js",
"dev": "nodemon server.js"

Now, let's create a file named server.js. Create a folder for storing the files Inside the server.js write the following code.

const express = require('express');
const app = express();
const path = require('path');
const multer = require('multer');
const uuid = require('uuid');
const cors = require('cors');
const bodyparser = require('body-parser');

// set the upload limit, in this case I gave it 50 mb
app.use(bodyparser.urlencoded({ limit: '50mb', extended: true }))
app.use(cors()) // we are allowing every sites to send API call
app.use(express.urlencoded({ extended: true }));

// simple html template, it is not our main focus
app.get('/', (req, res) => {
    const fileName = path.join(__dirname, 'index.html')
    res.sendFile(fileName, (error) => {
        console.log(error)
    })
})

// the actual code starts from here
/*
    we are using multer.diskStoarge() to take the full control for 
    uploading files
*/
const storage = multer.diskStorage({
    // `cb` stands for callback
    destination: (req, file, cb) => {
        cb(null, './files') 
        // cb(error, directory_name)
    },
    /*    
        destination function is a function to set the path for our files.
        in this case, we are using the folder "files". the "files" folder
        is located in our main directory.
    */
    filename: (req, file, cb) => {
        const extension = path.extname(file.originalname);
        cb(null, uuid.v4() + extension);
    // giving the file name, here we are naming it with uuid.extension
    }
    /*
        filename function gives a filename for the uploaded file
    */
})

const upload = multer({ storage: storage })
// upload middleware

app.post('/files', upload.array('image', 5), (req, res, next) => {
    const uploadedFiles = req.files.map((file) => file.filename);
  // mapping through all of the files and setting file name for every files
    res.json({ files: uploadedFiles });
    console.log('file uploaded');
    next()
})
/*
    the above lines we are posting to '/files', then we are adding the
    upload middleware. we will upload multiple files ( 5 files ) ,so we
   have written `upload.array('image',5)`. the file form name will be image
*/
app.listen(5000, () => {
console.log("Server is running")
})

Open the terminal and run the following command

npm run dev

Now, our server is running on localhost:5000

Frontend

Open a folder in the file explorer and open the terminal.

We will create a React.js project using Vite. Vite is an awesome tool for creating React apps. To do so, open the terminal and run the following command.

npx create-vite@latest

Now, type your project name. Hit Enter. Select your React and JavaScript. move to the project directory and run,

npm install

Open the React project in VS Code. Create a new file named Form.jsx in the `src` folder. This is our Form component. The code will be like this.

// Form.jsx
import { useState } from "react";


const Form = () => {
    const [files, setFile] = useState([])

    const sendFile = (event) => {
        event.preventDefault();
    // creating a new form data
        const formData = new FormData();
    // adding files to the form data
        [...files].forEach((file) => {
            /* Here we give the form name 'image'. this same name in the
               upload.array('image') middleware
            */
            formData.append('image', file);
        })


        fetch("http://localhost:5000/files", {
            method: 'POST',
            body: formData
        })
            .then(res => { })
    }
    return (
        <div>
            <form onSubmit={sendFile}>
                <input type="file" name="image" id="image" onChange={e => setFile(e.target.files)} multiple />
                <button>Send</button>
            </form>
        </div>
    )
}

export default Form

The App.jsx file will be following.

// App.jsx
import './App.css'
import Form from './Form'

function App() {
    return (
        <>
          <Form />
        </>
  )
}

export default App

Done. Now open the React app in your browser. Check whether everything is working or not.