DEV Community

Faris Durrani
Faris Durrani

Posted on

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

Today, we'll learn how to download a file from the backend server to be downloaded in the client 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 download button 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 download progress.

npm i axios
Enter fullscreen mode Exit fullscreen mode

We will also install downloadjs to download a blob to the hard disk:

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

In frontend/src/app/page.tsx, let's create a very basic file download button with its functionalities:

"use client";
import { useEffect, useState } from "react";
import axios from "axios";
import download from "downloadjs";

export default function Home() {
  async function handleDownloadFile() {
    const filename = "a.json";
    const res = await axios.get(
      "http://localhost:8000/downloadFile?" +
        new URLSearchParams({ filename: filename }),
      {
        responseType: "blob",
        onDownloadProgress: (progressEvent) => {
          console.log(
            "Download progress: " +
              Math.round(
                (progressEvent.loaded / (progressEvent.total ?? 1)) * 100
              ) +
              "%"
          );
        },
      }
    );
    console.log(res);
    const data = res.data as Blob;
    download(data, filename);
    console.log("Downloaded");
  }

  return (
    <div>
      <button onClick={() => handleDownloadFile()}>Download</button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Create downloader in backend

Let's first create the file to download in the server. Create a new file backend/sample_downloads/a.json which contains this very simple text:

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

And modify backend/index.ts to open a route to download the file:

import express, { Request } from "express";
import cors from "cors";

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

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

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

app.get(
  "/downloadFile",
  (req: Request<void, Blob, void, { filename: string }>, res) => {
    const filename = req.query.filename;
    res.status(200).download(`./sample_downloads/${filename}`);
  }
);

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

Download and verify

Back in http://localhost:3000, click the Download button and verify the file is being downloaded. Of course, make sure you've started both the frontend and backend already:

Downloading file on client

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.

Top comments (0)