0

I have one Python API that returns a PDF file which when called directly from my terminal downloads the PDF fine and it all looks good when opened. However, I have a Nuxt web app supported by an Express backend which I want to use to open the PDF file in a new tab and to be downloadable. All I am getting in response from the Python API is a string which looks like this:

'%PDF-1.4\n' +
    '1 0 obj\n' +
    '<<\n' +
    '/Title (��\x00F\x00l\x00o\x00o\x00d\x00S\x00m\x00a\x00r\x00t)\n' +

plus a few thousand more chars.

This string is what opens in the new tab. It looks like some encoded data, but I am not really sure which makes proceeding a bit harder.

I am assuming the Python API is fine, so I am thinking I need to do more with Express/Nuxt to make it work. The call to the Python API in Express is:

const response = await axios.get(
    url, { headers: { "X-API-Key": process.env.FS_UPRN_API_KEY } }
);
res.setHeader("Content-type", "application/pdf")
res.setHeader('Content-Transfer-Encoding', 'binary');
res.setHeader('Accept-Ranges', 'bytes');
res.send(response.data)

In the Nuxt frontend:

 this.$axios.get(`/api/uprn?uprn=${this.clickedUprn}`)
   .then(response => {
       window.open("", "_blank").document.write(response.data);

I have tried numerous configurations with different headers but haven't had any luck. How do I achieve the desired outcome?

  • 1
    _"It looks like some encoded data"_ - the actual _data_ in there is just what the binary content of a PDF looks like. But I am not sure why any API would return you that "hacked" into a multitude of JavaScript text literals - is this _really_ what you get returned from that API, or has this been manipulated by whatever you used to make that debug output, perhaps? You say, _"when called directly from my terminal downloads the PDF fine"_ - so I am assuming it is _not_ actually in the format you have shown above? – CBroe Nov 30 '22 at 12:10
  • _If_ that endpoint returns you a PDF directly, then it would probably be easiest to not use axios.get to begin with - but to directly open the URL in a new window instead. – CBroe Nov 30 '22 at 12:11
  • @CBroe yea it's not meant to look like that, it's meant to be a report document that is legible to a human. When I run `curl -o out.pfd` against the python API, I download the document fine. I just want to do that in the Express backend so it can be displayed in the browser fine. I can't do that directly in the frontend for security reasons, so the express API is just a proxy basically. – sobmortin354 Nov 30 '22 at 14:43
  • Why can't you do `window.open(\`/api/uprn?uprn=${this.clickedUprn}\`)` directly? – CBroe Nov 30 '22 at 14:47
  • Mainly because the API requires an API Key that would then be exposed to the browser – sobmortin354 Nov 30 '22 at 14:55
  • I suspect I have to stream it into memory / file to download it in JS? – sobmortin354 Nov 30 '22 at 15:04
  • 1
    _"Mainly because the API requires an API Key that would then be exposed to the browser"_ - how would that expose your API key all of a sudden? You are already making the request for the URL `/api/uprn?uprn=...` from the client side, without exposing your API key. So how would using that _exact same_ URL directly in `window.open(...)` change anything now? – CBroe Nov 30 '22 at 15:10
  • Well, it's a bit confusing because there is one API (the python one) that creates the PDF and returns it. One place that calls it is a website, so theres the frontend which passes JWT from frontend to the Express API which verifies the token and then makes the request to the python API with the key. So its a bit long winded but needs to be this way. – sobmortin354 Nov 30 '22 at 15:14
  • 1
    Okay, the info that you are sending & validating the JWT, was missing so far. Converting your received binary PDF data to a Data URI should work, https://stackoverflow.com/a/46064696/1427878 (only you can't open that data URI in the new window _directly_ any more, browsers will block that - so you will need to put an iframe into the popup first, and then assign the data URI as source for that.) – CBroe Nov 30 '22 at 15:19
  • Unfortunately not, it opens a new tab with an iframe that says `webpage at not available.` where pdfstring is what I referenced before. Do I need to do anything to that string to make it usable where `yourDocumentBase64VarHere` is used in the question you linked to? I am just putting that PDF string in – sobmortin354 Nov 30 '22 at 15:48

1 Answers1

0

What worked for me was encoding the contents of the file to base64 and then proceeding with the answer to this question: Opening PDF String in new window with javascript

Jakye
  • 6,440
  • 3
  • 19
  • 38