THE SITUATION:
Frontend: Vue. Backend: Laravel.
Inside the web app I need to let the user download certain pdf files:
- I need Laravel to take the file and return it as a response of an API GET request.
- Then inside my Vue web app I need to get the file and download it.
THE CODE:
API:
$file = public_path() . "/path/test.pdf";
$headers = [
'Content-Type' => 'application/pdf',
];
return response()->download($file, 'test.pdf', $headers);
Web app:
downloadFile() {
this.$http.get(this.apiPath + '/download_pdf')
.then(response => {
let blob = new Blob([response.data], { type: 'application/pdf' })
let link = document.createElement('a')
link.href = window.URL.createObjectURL(blob)
link.download = 'test.pdf'
link.click()
})
}
OUTCOME:
Using this code I do manage to download a pdf file. The problem is that the pdf is blank.
Somehow the data got corrupted (not a problem of this particular pdf file, I have tried with several pdf files - same outcome)
RESPONSE FROM SERVER:
The response itself from the server is fine:
PDF:
The problem may be with the pdf file. It definitely looks corrupted data. This is an excerpt of how it looks like the response.data
:
THE QUESTION:
How can I properly download a pdf file using Laravel for the API and Vue for the web app?
Thanks!
You won't be able to do the download from
Laravel
toVue
since both are running at different ports I assume.Even if you try something like this.
It won't help as you are sending headers to the
Laravel
Port Try usingVue js
libraries and try to send that pdf content on the libraryTry this Get help from here
SOLUTION:
Due credits goes to @Sagar to point me in the right direction.
The code above was correct. What was missing was adding the proper
responseType
asarraybuffer
.I got scared by those
????
inside the response, and that was misleading me. Those question marks were just okay since pdf is a binary data and is meant to be read by a proper reader.THE ARRAYBUFFER:
And arraybuffer is precisely used to keep binary data.
This is the definition from the mozilla website:
And the
ResponseType
string indicates the type of the response. By telling its an arraybuffer, it then treats the data accordingly.And just by adding the responseType I managed to properly download the pdf file.
THE CODE:
This is corrected Vue code (exactly as before, but with the addition of the responseType):
EDIT:
This is a more complete solution that take into account other browsers behavior: