Build a React file upload component with Node.js

There are a number of different ways you can upload files for storage from a React application. In this tutorial we’ll be using Node.js with Express, and Multer a middleware for handling multipart form data.

Before beginning you’ll need to have Node.js installed which can be done by following the instructions on the offical website.

Building the React frontend

We’ll start by setting up the project using Create React App and installing axios a promise based HTTP client that simplifies API requests. Open a terminal window and run the following commands:

npx create-react-app file-upload
cd file-upload
npm install axios

Create a new file called FileUpload.js and we can get started with the code.

First import React, { useState } as we’ll store file data in state, and axios:

import React, { useState } from "react";
import axios from "axios";

Then add a FileUpload() function that contains a simple file upload form:

function FileUpload() {  
  return (
    <form onSubmit={uploadFile}>
      <input type="file" name="file" onChange={getFile} required />
      <input type="submit" name="upload" value="Upload" />
    </form>
  );
}
export default FileUpload;

Next still inside the FileUpload() function we’ll add the functionality for when the onChange event is triggered. We first declare a variable for the fileData then when the function is called save the data using setFileData:

const [fileData, setFileData] = useState("");
const getFile = (e) => {
  setFileData(e.target.files[0]);
};

Complete the FileUpload() function by adding the code to handle the onSubmit event:

 const uploadFile = (e) => { 
    e.preventDefault();   
    const data = new FormData();
    data.append("file", fileData);
    axios({
      method: "POST",
      url: "http://localhost:5000/upload",
      data: data,
    }).then((res) => {       
        alert(res.data.message);
    });
  };

This will POST the data from fileData to our Node.js endpoint at http://localhost:5000/upload and once complete alert a response with the status of the upload.

Complete the frontend by loading the component into App.js as follows:

import React from 'react';
import FileUpload from "./FileUpload";
import logo from './logo.svg';
import './App.css';

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />       
        <FileUpload />
      </header>
    </div>
  );
}

export default App;

If you run the npm run start command you should see the following in the browser:

Alt Text

Building the Node.js backend

For the backend we’ll need to install the following Node.js dependencies:

npm install express cors multer
  • express – used to create the endpoint (URI) for the POST request.
  • cors – allows the frontend and backend to share resources.
  • multer – middleware for handling the file uploads.

We’ll also install nodemon as a dev dependency to monitor the server for file changes so a restart isn’t required on each code update:

npm install nodemon --save-dev

Next create a server.js file, include the dependencies, and define the app:

const express = require("express");
const multer = require("multer");
const cors = require("cors");
const app = express();
app.use(cors());

The only config required for multer is to specify the folder in which our files will be saved. Here we’ll save them to a /uploads folder in the /public directory so they can be accessed by the frontend if required:

var upload = multer({ dest: "../public/uploads/" });

Now we’ll handle the POST request.

If file data upload the file, otherwise no file was found, or a server error occurred:

app.post("/upload", upload.single("file"), async (req, res) => {
  try {    
    if (req.file) {
      res.send({
        status: true,
        message: "File Uploaded!",
      });
    } else {
      res.status(400).send({
        status: false,
        data: "File Not Found :(",
      });
    }
  } catch (err) {
    res.status(500).send(err);
  }
});

Finally let’s tell the app to listen to port 5000:

app.listen(5000, () => console.log("Server Running..."));

Start the server with the following command and then we can test the form:

nodemon server.js

If the file upload was successful you’ll get a “File Uploaded!” alert message. You can double check the upload was successful by browsing the public/uploads folder. If the upload failed check the server console for more details.