How to upload a file in a full-stack React app
Published: 2023-07-23 20:09:49

Today, we'll learn how to upload a file from the frontend client to be downloaded in the backend server.

The frontend will use React Next.JS and the backend will use Node.JS.

## Create your frontend and backend projects
See [A simple React Next + Node app in Typescript](https://dev.to/farisdurrani/a-simple-react-next-node-app-in-typescript-2mci).

## Create input in frontend

First, install axios in `frontend/`. We're using axios instead of the native fetch to post the file since we want to print the upload progress.

```sh
npm i axios
```

In `frontend/src/app/page.tsx`, let's create a very basic file input:

```tsx
"use client";
import { useEffect, useState } from "react";
import axios from "axios";

export default function Home() {
  async function handleUploadFile(file?: File) {
    if (!file) return;
    const formData = new FormData();
    formData.append("file", file);
    const res = await axios.post("http://localhost:8000/uploadFile", formData, {
      onUploadProgress: (progressEvent) => {
        console.log(
          "Upload progress: " +
            Math.round(
              (progressEvent.loaded / (progressEvent.total ?? 1)) * 100
            ) +
            "%"
        );
      },
    });
    console.log(res);
  }

  return (
    <div>
      <form>
        <input
          type="file"
          name="name"
          onChange={(e) =>
            handleUploadFile((e.target as HTMLInputElement).files?.[0])
          }
        />
      </form>
    </div>
  );
}

```

Hence, http://localhost:3000 will look like:

![File input in frontend](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r86wqvzopr182m463y80.png)

## Set up multer in backend

Multer is the service we'll use as the middleware to store the received file in the hard disk.

Let us install multer first:
```sh
npm i multer @types/multer
```

Then, modify `backend/index.tsx` to the following:
```ts
import express from "express";
import cors from "cors";
import multer from "multer";


// Create express app
const app = express();

app.use(express.json());
app.use(cors());

app.get("/helloText", (req, res) => {
  res.send({ myResponse: "Hello World!" });
});

const upload = multer({ dest: "tmp/uploads/" });
app.post("/uploadFile", upload.single("file"), (req, res) => {
  console.log(req.file);
  res.send({ myResponse: "File uploaded successfully" });
});


app.listen(8000, () => {
  console.log(`Server is running on port ${8000}`);
});
```

We are adding the `/uploadFile` POST path where we will receive and download the file to store in directory `tmp/uploads/`.

## Upload and verify

I have this simple file called `a.json` which contains a very simple text:
```json
{
    "message": "Hello"
}
```

On localhost:3000, I am uploading this file through the input box. I am also opening the console log to see the upload progress:

![Uploading file](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dlptt2ot85rr3rt5wpvt.png)

And in the backend, I see a new file with a random name in `backend/tmp/uploads/`, which is a copy of the file I just uploaded:

![Uploaded file in backend](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/41h0e33vh6483tm09zx6.png)

Of course, this works for other types of files up to the size limit imposed by your browser and internet speed.

That's all, good luck!


***Safe harbor statement***
The information provided on this channel/article/story is solely intended for informational purposes and cannot be used as a part of any contractual agreement. The content does not guarantee the delivery of any material, code, or functionality, and should not be the sole basis for making purchasing decisions. The postings on this site are my own and do not necessarily reflect the views or work of Oracle or Mythics, LLC.

*This work is licensed under a* [*Creative Commons Attribution 4.0 International License*](http://creativecommons.org/licenses/by/4.0/)*.*