How to Implement File Download Button in Next. Js? (Window Is Not Defined)

I know 'window' or 'document' objects are not recognizable in React component before component mounts.

I'm trying to make a download button which receive processed excel file from the backend server. Before I'm using React I used to implement like this...

 <button onclick="download()">Download</button>
    <script>
        function download() {
            const URL = '
            window.location.href = URL
        }
    </script>

However, in Next.js or React, window object is not recognizable so I had to do the other way. Download URL is dynamic so I won't use next.config.js

pages/index.tsx

//...
const handleDownloadExcel = () => {
    router.push('/download')
  }
//...
return(
//...
      <button onClick={() => handleDownloadExcel()}>Download!</button>
//...

pages/download.tsx

import { useEffect } from 'react'
import { useRouter } from 'next/router'
const DownloadPage = () => {
    const router = useRouter();
    useEffect(() => {
        //I will pass this URL variable by props later on.
        const URL = '
        window.location.href = URL;
        router.push('/')
    }, [])

    return (
        <>
        </>
    )
}

export default DownloadPage;

Now I managed to download a file from server but it doesn't seem right. Is there any other way to do this?

3 Answers

You can use the window object in next js like this :

    <script>
        function download() {
            const URL = '
            if (typeof window !== "undefined"){
              window.location.href = URL
            }
        }
    </script>

Use the file-saver package to download our file.

To install it, run:

npm i file-saver

Then we can call the saveAs function from the package by writing:

import React from "react";
import { saveAs } from "file-saver";

export default function App() {
  const saveFile = () => {
    saveAs(
      "",
      "example.pdf"
    );
  };
  return (
    <div>
      <button onClick={saveFile}>download</button>
    </div>
  );
}

The first argument is the URL to download and the 2nd argument is the file name of the downloaded file.

Thank you for the script above. It solved the issue. I also found that in NextJS copying the file into /public/download/ prevents the - HEAD net::ERR_FAILED 200 bug.

And changing "example.pdf" to the intended file name prevents the downloaded file from being named “download.pdf” by default.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Sophia Al-Mansoor

Sophia Al-Mansoor

Global Business & E-Commerce Reporter

Sophia analyzes international trade, startup ecosystems, retail transformation, and supply chain logistics for modern digital publications.

Share this article
Twitter Facebook Pinterest