How to upload a file in a full-stack React app

Faris Durrani - Jul 23 '23 - - Dev Community

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.

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.

npm i axios
Enter fullscreen mode Exit fullscreen mode

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

"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>
  );
}

Enter fullscreen mode Exit fullscreen mode

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

File input in frontend

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:

npm i multer @types/multer
Enter fullscreen mode Exit fullscreen mode

Then, modify backend/index.tsx to the following:

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

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:

{
    "message": "Hello"
}
Enter fullscreen mode Exit fullscreen mode

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

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

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.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Terabox Video Player