DEV Community

Michael Burrows
Michael Burrows

Posted on • Edited on • Originally published at w3collective.com

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
Enter fullscreen mode Exit fullscreen mode

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";
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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]);
};
Enter fullscreen mode Exit fullscreen mode

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);
    });
  };
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode
  • 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
Enter fullscreen mode Exit fullscreen mode

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());
Enter fullscreen mode Exit fullscreen mode

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/" });
Enter fullscreen mode Exit fullscreen mode

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);
  }
});
Enter fullscreen mode Exit fullscreen mode

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

app.listen(5000, () => console.log("Server Running..."));
Enter fullscreen mode Exit fullscreen mode

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

nodemon server.js
Enter fullscreen mode Exit fullscreen mode

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.

Top comments (0)