How to download a file in a full-stack React app
Published: 2023-07-23 20:43:18

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](https://dev.to/farisdurrani/a-simple-react-next-node-app-in-typescript-2mci).

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

```sh
npm i axios
```

We will also install `downloadjs` to download a blob to the hard disk:
```sh
npm i downloadjs @types/downloadjs
```

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

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

## 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:
```json
{
  "message": "Hello"
}
```

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

```ts
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}`);
});
```

## 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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ikqhm7wvkfr4utcpv2p3.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/)*.*