0

I am using JQuery to send an AJAX request to a Node server (using Hapi). The server responds with a PDF file correctly, but I am trying to save the file locally. The catch is that the PDF should only return if the POST sent the right data. It's "protected" in other words and I don't want to just expose it publicly.

Frontend code:

$.get('http://localhost:3000').done(function (data) {
  console.log(data);
});

Backend code:

server.route({
  method: 'GET',
  path: '/',
  handler: async (request, h) => {
    return h.file('./static/sample.pdf', {
      mode: 'attachment',
      filename: 'sample.pdf'
    })
  }
});

I receive the data but nothing happens in the front-end UI. How can I download the PDF that is sent automatically?

Mike M
  • 4,879
  • 5
  • 38
  • 58
  • 1
    don't use ajax - just set window.location, since it's an attachment, the file save dialog "should" pop up – Jaromanda X May 22 '20 at 10:11
  • if you must use ajax, then look at something like https://github.com/eligrey/FileSaver.js/ – Jaromanda X May 22 '20 at 10:17
  • @JaromandaX The problem is that my PDF should only be sent as a reply to the POST, and only if the POST was successful. In other words, I do not want to expose it in a public API. – Mike M May 22 '20 at 11:00
  • 1
    Does this answer your question? [Handle file download from ajax post](https://stackoverflow.com/questions/16086162/handle-file-download-from-ajax-post) – freedomn-m May 22 '20 at 13:53
  • @freedomn-m Sure, but the answer given below is actually shorter. – Mike M May 22 '20 at 15:40
  • you may want to check if the answer works in all browsers – Jaromanda X May 22 '20 at 23:58

1 Answers1

1

You can achieve that with html5 using

<a href="http://link/to/file" download="FileName">Download it!</a>

Notice that this works only for same-origin URLs, or the blob: and data: schemes. And this gets overridden by the Content-Disposition header from the server.

If you want to do this programatically you could do this

    const element = document.createElement("a")
    element.setAttribute(
      "href",
      // you could also use base64 encoding here like data:application/pdf;base64,
      "data:text/plain;charset=utf-8," + encodeURIComponent('pdf binary content here') 
    )
    element.setAttribute("download", "file.pdf")

    element.style.display = "none"
    document.body.appendChild(element)

    element.click()

    document.body.removeChild(element)

Anyway this is only a useful method if u want to create/modify the downloaded data from the client side, but if u are getting it as it is from the server side then its better just to open a new url, letting the browser handle it.

ehab
  • 7,162
  • 1
  • 25
  • 30