Let me say that what follows was only tried with Chrome.
What’s the problem?
It all started with JWT considerations (if you want to know more you can go here). I’m building a custom B2B solution where access to all resources is authenticated. This is easy for the api part, but not so easy when dealing with files, like pdf files.
Get the file from the api (authenticated)
So, the first step is the get the file, probably with the same approach used for the other endpoints of the api. In my case, I’m using Feathers.js. You can read about this framework in feathersjs.com. And, specifically, my api is returning a blob. We could use other approaches, namely base64 encoding. But is a well-established fact that they result in a larger payload.
And, of course, we will send the JWT token when asking for the file. This way we have an authenticated request.
Now, we have a blob
After getting the pdf file, we have a blob. Remember, blobs are immutable, raw data. To deal with blobs the usual way is window.URL.createObjectURL(blob).
This method “creates a DOMString containing a URL representing the object given in the parameter” (taken from the documentation).
What can we do with this url? Mostly two things: show the pdf file in the browser (same tab or new tab/window) or download the file. Let’s see the first option.
Show pdf in the browser
My preferred option is to show the pdf in the browser, specifically in a new tab. To do it, we just need something like window.open(url). But if you want to use the same tab window.location = url is sufficient.
If your aim is the pdf to be downloaded, another strategy can be used. We can create an <a> tag with the “download” attribute. Documentation says “This attribute instructs browsers to download a URL instead of navigating to it, so the user will be prompted to save it as a local file. If the attribute has a value, it is used as the pre-filled file name in the Save prompt (the user can still change the file name if they want).”
We create the element, fill the necessary data and call the click() method:
Now I have the feeling that all this is clearer!