Vue + Laravel: How to properly download a PDF file? Vue + Laravel: How to properly download a PDF file? vue.js vue.js

Vue + Laravel: How to properly download a PDF file?


SOLUTION:

The code above was correct. What was missing was adding the proper responseType as arraybuffer.

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:

The ArrayBuffer object is used to represent a generic, fixed-lengthraw binary data buffer. You cannot directly manipulate the contents ofan ArrayBuffer; instead, you create one of the typed array objects ora DataView object which represents the buffer in a specific format,and use that to read and write the contents of the buffer.

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):

downloadFile() {  this.$http.get(this.appApiPath + '/testpdf', {responseType: 'arraybuffer'})    .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()    })}

EDIT:

This is a more complete solution that take into account other browsers behavior:

downloadContract(booking) {  this.$http.get(this.appApiPath + '/download_contract/' + booking.id, {responseType: 'arraybuffer'})    .then(response => {      this.downloadFile(response, 'customFilename')    }, response => {      console.warn('error from download_contract')      console.log(response)      // Manage errors      }    })},downloadFile(response, filename) {  // It is necessary to create a new blob object with mime-type explicitly set  // otherwise only Chrome works like it should  var newBlob = new Blob([response.body], {type: 'application/pdf'})  // IE doesn't allow using a blob object directly as link href  // instead it is necessary to use msSaveOrOpenBlob  if (window.navigator && window.navigator.msSaveOrOpenBlob) {    window.navigator.msSaveOrOpenBlob(newBlob)    return  }  // For other browsers:  // Create a link pointing to the ObjectURL containing the blob.  const data = window.URL.createObjectURL(newBlob)  var link = document.createElement('a')  link.href = data  link.download = filename + '.pdf'  link.click()  setTimeout(function () {    // For Firefox it is necessary to delay revoking the ObjectURL    window.URL.revokeObjectURL(data)  }, 100)},


You won't be able to do the download from Laravel to Vue since both are running at different ports I assume.

Even if you try something like this.

public function getDownload()    {        //PDF file is stored under project/public/download/info.pdf        $file= public_path(). "/download/info.pdf";        $headers = [              'Content-Type' => 'application/pdf',           ];    return response()->download($file, 'filename.pdf', $headers);    }

It won't help as you are sending headers to the Laravel Port Try using Vue js libraries and try to send that pdf content on the library

Try thisGet help from here


downloadFile: function () {            this.$http.post('{{ route('download.download') }}', {                _token: "{{ csrf_token() }}",                inputs: this.inputs            },{responseType: 'arraybuffer'}).then(response => {                var filename = response.headers.get('content-disposition').split('=')[1].replace(/^\"+|\"+$/g, '')                var url = window.URL.createObjectURL(new Blob([response.body],{type:response.headers.get('content-type')}))                var link = document.createElement('a')                link.href = url                link.setAttribute('download', filename)                document.body.appendChild(link)                link.click()            });        },