Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating PDF from request response doesn't work with axios but works in native xhr

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.

like image 631
Victor Avatar asked Apr 28 '17 21:04

Victor


People also ask

Is Axios a XHR?

The Axios library wraps the complex XHR syntax and provides an abstract and declarative way to make requests from the browser as well as in a node environment.

What is Axios responseType?

By default, responseType is set to 'json' , which means Axios will try to parse the response as JSON.

How do I send HTTP requests with Axios?

Sending HTTP requests with Axios is as simple as giving an object to the axios () function that contains all of the configuration options and data. Let's look at the configuration options in more detail: data: The data specified with this option is sent in the body of the HTTP request in POST, PUT, and PATCH requests.

Does Axios automatically convert requests to JSON?

Although Axios automatically converts requests and responses to JSON by default, you can override this behaviour and specify your own transformation mechanism. When working with an API that only supports a specific data format, such as XML or CSV, this is quite beneficial.

How do I get data from a server using Axios?

Axios can make a GET request to “get” data from a server. The axios.get () method is used to make an HTTP get request. There are two parameters that must be passed to the get () method.

Why is the response provided as a promise in Axios?

The response is provided as a promise because Axios is promise-based. To obtain the response and catch any errors, we must utilize the then () and catch () functions. Let's look at how we can deal with a POST request's response.


2 Answers

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!

like image 79
Nayab Siddiqui Avatar answered Sep 18 '22 06:09

Nayab Siddiqui


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]));
        });
like image 35
Don F Avatar answered Sep 20 '22 06:09

Don F