Sponsored

How to Implement Download Files in NextJS using an API Route

Jasser Mark Arioste

Jasser Mark Arioste

How to Implement Download Files in NextJS using an API Route

Hello, hustlers! In this tutorial, you'll learn how to send files from an API route in NextJS 13 /app and /api folders. 

Sponsored

Introduction#

It's common practice to store files to a third-party service like AWS S3, Digital Ocean Spaces, or Azure blob storage but we don't want the client to access the URL from those services directly. It's a best practice to create a proxy like an API route in your backend server. 

The diagram below illustrates the process described above:

NextJS Typical Download File Architecture.
Sponsored

Tutorial Objectives#

In this tutorial, you'll learn the following:

  1. Create an API route to send files using the /app router of NextJS 13.
  2. Create an API route to send files using the /pages directory of NextJS 12.

This way, you'll have two options depending on what version of NextJS you are using. The implementation is different in both options but I prefer using the /app directory since it's more straightforward and I find the code more readable.

Sponsored

Option 1: Using the /app router#

First, let's create the route by creating the file /app/download/[filename]/route.ts. Your directory should look like this:

šŸ“ app
  šŸ“ download
    šŸ“ [filename]
          route.ts
123

The route.ts file is a special file for route handlers in NextJS that indicates that a path is an API route. Here we can access the API through the following route for example: /api/download/dummy.pdf.

Here's how to implement the actual download:

type GetParams = {
  params: {
    filename: string;
  };
};

// export an async GET function. This is a convention in NextJS
export async function GET(req: Request, { params }: GetParams) {
  // filename for the file that the user is trying to download
  const filename = params.filename;

  // external file URL
  const DUMMY_URL =
    "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf";

  // use fetch to get a response
  const response = await fetch(DUMMY_URL);

  // return a new response but use 'content-disposition' to suggest saving the file to the user's computer
  return new Response(response.body, {
    headers: {
      ...response.headers, // copy the previous headers
      "content-disposition": `attachment; filename="${filename}"`,
    },
  });
}
1234567891011121314151617181920212223242526

Now, once we go to /api/download/dummy.pdf, you should see the file being downloaded by the browser:

File downloaded through NextJS app route handlers.
Sponsored

Option 2: Using the /pages/api directory#

Next, let's implement file download using the /pages directory. If you're using Next 13 but haven't adapted to the new /app directory, then you can use this method. Otherwise, I recommend the previous method since it's much easier to implement.

I find that using axios package is easier in this scenario so let's install it first:

yarn add axios
1

First, create the file /pages/api/_download/[filename].ts. I used _download to avoid route conflict with the /app folder.

import axios from "axios";
import { NextApiRequest, NextApiResponse } from "next";
import { Readable } from "stream";

async function handler(req: NextApiRequest, res: NextApiResponse) {
  // get the filename for the file that the user is trying to download
  const filename = req.query.filename;

  // external file URL
  const DUMMY_URL =
    "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf";

  // use axios to get a Readable stream response
  const { data } = await axios.get<Readable>(DUMMY_URL, {
    responseType: "stream",
  });

  res.setHeader("content-disposition", `attachment; filename="${filename}"`);

  // pipe the data to the res object
  data.pipe(res);
}

export default handler;

123456789101112131415161718192021222324

Here, the code is pretty similar to the first option, but instead of returning a Response object, we use .pipe to copy all the data from the stream to the res object.

Sponsored

Full Code#

You can access the full code at my GitHub repo: jmarioste/next-js-download-file

Sponsored

Conclusion#

You learned how to create download APIs using NextJS /app router and /pages/api routes.

If you like this tutorial, please leave a like or share this article. For future tutorials like this, please subscribe to our newsletter or follow me on GitHub.

Sponsored

Resources#

Credits: Image by Vero_Fasching from Pixabay

Tags:
Share this post!

Related Posts

Sponsored

Subscribe to our newsletter

Get up-to-date on latest articles on react.js, node.js, graphql, full-stack web development. No Spam. Helpful articles to improve your skills. Sent directly to your inbox.