Initiate a POST request to download the file upon clicking the button

How can I initiate a file download when a button is clicked?

During testing, I noticed that sending a GET request using

<Link href="/api/generate-pdf">
works perfectly and the PDF file gets saved. However, when I use a button to hit the API, the download does not start.

This is how my button looks in a Next.js 13 Client Component:

function generatePdf() {
    fetch("/api/generate-pdf", {
      method: "POST",
      headers: {
        "Content-type": "application/pdf",
      },
      body: JSON.stringify(store),
    })
}

<Button onClick={generatePdf} type="button">
    Generate PDF
</Button>

API Route Handler:

export async function POST(request: Request) {
  console.log("/api/generate-pdf POST Request")
  try {
    // ...
    // generate the pdf file
    const generatedPdf = doc.output("blob")
    const filename = "pac.pdf"
    const res = new Response(generatedPdf, {
      status: 200,
      headers: {
        "Content-Type": "application/pdf",
        "content-disposition": `attachment; filename="${filename}"`,
      },
    })
    return res
  } catch (error) {
    console.log(error)
    return NextResponse.json("Internal Error", { status: 500 })
  }
}

Answer №1

It seems like the issue you are facing is related to how the fetch API handles file downloads compared to direct links. When you click a button, the fetch API sends a request and receives a response, but it does not automatically initiate the file download like a direct link would.

To work around this, you can adjust your generatePdf function to create a Blob object from the response and then generate a URL for that Blob. One approach is to programmatically simulate a click on a hidden anchor element that references this URL to trigger the file download, similar to this:

async function generatePdf() {
  const response = await fetch("/api/generate-pdf", {
    method: "POST",
    headers: {
      "Content-type": "application/pdf",
    },
    body: JSON.stringify(store),
  });

  const blob = await response.blob(); // creates a new Blob object
  const url = window.URL.createObjectURL(blob); 
  const a = document.createElement("a"); 
  a.href = url; 
  a.download = "yourPDF.pdf";  
  a.click(); 
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Combine identical arrays of object keys into one unified array

I am striving for this particular output [ productId:106290, productserialno:[{ "12121", "212121" }] ] ...

Error message: "Module not found" encountered while executing test case

I am a beginner in node and nightwatch and I have followed all the initial instructions from setting up node, npm, selenium standalone, starting the selenium driver. I also downloaded the chrome driver and placed it in the same directory. I created the con ...

Find the current location of the scroll bar on the view port

Currently, I am utilizing the Addazle React grid for my project. However, I need to incorporate endless scrolling functionality which is not already included in this grid system. Thus, I am tasked with devising my own solution for this issue. To successful ...

Is it possible to update the version of NPM?

Having an issue with installing packages for my React-Native project due to a NPM version error. How can I upgrade it? Currently using version 4 ...

The Date Picker pops up automatically upon opening the page but this feature is only available on IE10

There seems to be an issue with the date picker opening automatically on IE10, while it works fine in Firefox where it only appears when you click on the associated text box. Does anyone have insight into why this might be happening specifically in IE10? ...

Error message: The Slick Carousal encountered an unexpected problem - TypeError:undefined is not a function

I'm having an issue with a script for a Slick Carousel inside of some Ajax Tabs. I keep encountering the Uncaught TypeError: undefined is not a function error, but I'm unsure what exactly it's pointing to. $(document).ready(function(){ ...

using node and express to route and pass variables to a required module

In my primary index.js file, I have the following code: var express = require('express') require("dotenv").config(); const db = require('./services/db_service').db_connection() const customers = require('./routes/custo ...

Unable to make a div grow within a Popper component in a React.js application

I'm facing a challenge with implementing a CSS feature and need some assistance. https://i.stack.imgur.com/KXpGd.png Upon clicking the "See link options" button, the content loads but spills out of the popper. My goal is to have the popper expand in ...

Ways to display the data within a BLOB object

On this page, the user is showcasing a table with three columns - tipo_esame (string), data_esame (string), and uri (BLOB). const archiveItems = this.state.archive.map((archive, i) => { return ( <tr key={archive.hash_referral}> <td ...

Utilizing Typescript to Inject Generics and Retrieve the Name of an ES6 Module

I am currently working on developing a versatile repository using: Typescript ES6 Angular 1.x However, I am facing challenges in determining the correct way to inject the Entity and retrieve its module name. The main reason for needing the name: I adh ...

Transform this JavaScript into Vue 3 code

Hey there! I'm currently working on implementing dark mode into my project by following a tutorial. However, the tutorial is based on JavaScript and not Vue, so I'm having some trouble converting this particular section of code to work with Vue 3 ...

Ways to insert text at the start and end of JSON data in order to convert it into JSONP format

Currently, I am working on a project where I need to add a prefix "bio(" and a suffix ")" to my JSON data in order to make it callable as JSONP manually. I have around 200 files that require this modification, which is why I am looking for a programmatic ...

Glitches and sudden jumps occur when using the useMediaQuery function in Material UI

Implementing Material UI's useMediaQuery() hook, I have embedded the theme provider and initialized a variable in this way: const theme = useTheme(); const isSmall = useMediaQuery(theme.breakpoints.down('sm') ); I am utilizing the isSmall v ...

Turn off automatic vertical scrolling when refreshing thumbnails with scrollIntoView()

My Image Gallery Slider has a feature that uses ScrollIntoView() for its thumbnails, but whenever I scroll up or down the page and a new thumbnail is selected, it brings the entire page back to the location of that thumbnail. Is there a way to turn off t ...

Using jQuery to display a div after a 2-second delay on my website, ensuring it only appears once and does not reappear when the page is refreshed or when navigating to a

I manage a website that includes a blog section. Every time someone visits the site, I want a popup window to appear. (To achieve this, follow these steps - Utilize jQuery for showing a div in 5 seconds) I would like this popup to only be displayed once ...

Combine Typescript files from a dependent module to aid in debugging within a Next.js application

Trying to debug a project written in Typescript using Next.js, but facing issues with bundling TS files from a local dependent common library. Only JS files are included, which is not sufficient for debugging. The goal is to bundle all TS files from the w ...

Leveraging the power of node pkg to generate standalone executables while configuring npm

I have successfully used pkg to create an executable file for my node js application. Everything is working fine in that aspect. However, I am also utilizing the config module to load yaml configuration files based on the environment. During the packaging ...

NodeJS rendering method for HTML pages

We are in the process of developing a fully functional social networking website that will resemble popular platforms like Facebook or Instagram. Our plan is to utilize Node.js on the server side and we are currently exploring the best technology for rende ...

Having issues with CSS animation keyframes not functioning properly in NextJS

Currently, I have a straightforward component in NextJS that is displaying "HI" upon loading. This component fades in when rendered, but I am facing an issue while trying to pass a prop to make it fade out. The problem lies in the fact that even though the ...

What is the best way to use JavaScript in an ASP.NET Controller to navigate to a different webpage?

I'm currently developing a website using Angular 1 with an ASP.NET MVC backend. I'm trying to create a link that will gather certain parameters using JavaScript, retrieve the correct URL from a controller, and then redirect the user to a differen ...