Build a React file upload component with Node.js
Tags: node, react, javascript, tutorial
Published: 2020-09-30 00:33:41

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](https://nodejs.org/).

##Building the React frontend

We’ll start by setting up the project using [Create React App](https://create-react-app.dev/) and installing [axios](https://www.npmjs.com/package/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`:

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

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

```javascript
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`:

```javascript
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:

```javascript
 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:

```javascript
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](https://dev-to-uploads.s3.amazonaws.com/i/np06hngn9z0t2wxqcou9.png)

##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:

```javascript
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:

```javascript
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:

```javascript
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:

```javascript
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.