10

In order to force download PDF from server I tried to use axios and native xhr object. The reason is that I have to send post request, because I pass too much data to server, so the option with simple link (like site.ru/download-pdf won't work for me).

Even though I finally managed to do this with Xhr, I still don't have a clue why axios way doesn't work.

Here is how I do this with xhr and it works for me:

    let xhr = new XMLHttpRequest()
    xhr.open('POST', Vue.config.baseUrl + `order-results/${id}/export-pdf`, true)
    xhr.setRequestHeader("Authorization", 'Bearer ' + this.token())
    xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded")
    xhr.responseType = 'arraybuffer'

    xhr.onload = function(e) {
      if (this.status === 200) {
        let blob = new Blob([this.response], { type:"application/pdf" })
        let link = document.createElement('a')
        link.href = window.URL.createObjectURL(blob)
        link.download = 'Results.pdf'
        link.click()
      }
    };

    xhr.send("data=" + data);

Here is "axios-way" and I actually get PDF with correct number of pages, but they are all empty:

    axios.post(`order-results/${id}/export-pdf`, {
      data,
      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 = 'Results.pdf'
      link.click()
    })

Axios is already configured to send Authorization token. I put Application/x-www-form-urlencoded in xhr because otherwise I couldn't get data in server side.

Even though xhr works, I'd prefer to use axios since I use it everywhere and I'm just curios what I'm doing wrong. I tried different solutions, and only native xhr did the job.

Victor
  • 5,073
  • 15
  • 68
  • 120
  • Possible duplicate of [Force download GET request using axios](https://stackoverflow.com/questions/43432892/force-download-get-request-using-axios) – webnoob Oct 30 '17 at 09:02

4 Answers4

39

The following works for me:

axios.post("http://localhost:8080/reports/my-report/",
        data,
        {
            responseType: 'arraybuffer',
            headers: {
                'Content-Type': 'application/json',
                'Accept': 'application/pdf'
            }
        })
        .then((response) => {
            const url = window.URL.createObjectURL(new Blob([response.data]));
            const link = document.createElement('a');
            link.href = url;
            link.setAttribute('download', 'file.pdf'); //or any other extension
            document.body.appendChild(link);
            link.click();
        })
        .catch((error) => console.log(error));

Let me know if this helps.

Cheers!

Nayab Siddiqui
  • 1,971
  • 1
  • 15
  • 18
5

For whatever reason the pdf is downloading but any content passed is not appearing resulting in a blank pdf.

I found this code snippet that is similar but results in a pdf with content.

 axios({
                url: '/pdf',
                method: 'GET',
                responseType: 'blob', // important
            }).then((response) => {
                const url = window.URL.createObjectURL(new Blob([response.data]));
                const link = document.createElement('a');
                link.href = url;
                link.setAttribute('download', 'file.pdf');
                document.body.appendChild(link);
                link.click();
            });

there was some feedback stating that it didnt work on IE 11, I have not tested it but a solution was posted using FileSaver.js

axios({
            url: '/pdf',
            method: 'GET',
            responseType: 'blob', // important
        }).then((response) => {
            FileSaver.saveAs(new Blob([response.data]));
        });
Don F
  • 1,963
  • 2
  • 15
  • 18
  • This is a get request, which returns pdfs that display fine, but post requests seem to effect the response data which results in blank pdfs – conor909 Nov 24 '19 at 13:04
0

There is a special responseType: 'blob':

axios.post(`order-results/${id}/export-pdf`, {
  data,
  responseType: 'blob'
}).then((response) => {
  let link = window.URL.createObjectURL(blob)
  link.download = 'Results.pdf'
  link.click()
})

Or you can use window.open method:

axios.post(`order-results/${id}/export-pdf`, {
  data,
  responseType: 'blob'
}).then((response) => {
  window.open(URL.createObjectURL(response.data));
})
Slava
  • 1,559
  • 1
  • 12
  • 17
-2

You're getting empty PDF 'cause no data is passed to the server. You can try passing data using data object like this

axios.post(`order-results/${id}/export-pdf`, {
  data: {
    firstName: 'Fred'
  },
  responseType: 'arraybuffer'
}).then((response) => {
  console.log(response)

  let blob = new Blob([response.data], { type: 'application/pdf' } ),
      url = window.URL.createObjectURL(blob)

  window.open(url); // Mostly the same, I was just experimenting with different approaches, tried link.click, iframe and other solutions
});

By the way I gotta thank you so much for showing me the hint in order to download pdf from response. Thank ya :)

var dates = {
    fromDate: 20/5/2017,
    toDate: 25/5/2017
}

The way in which I have used is,

axios({
  method:'post',
  url:'/reports/interval-dates',
  responseType:'arraybuffer',
  data: dates
})
.then(function(response) {
    let blob = new Blob([response.data], { type:   'application/pdf' } );
    let link = document.createElement('a');
    link.href = window.URL.createObjectURL(blob);
    link.download = 'Report.pdf';
    link.click();
});
Martin Schneider
  • 3,268
  • 4
  • 19
  • 29
Roshimon
  • 1,991
  • 19
  • 16