web-dev-qa-db-fra.com

Forcer le téléchargement d'une requête GET à l'aide d'axios

J'utilise vuejs 2 + axios ..__ Je dois envoyer une requête get, transmettre des paramètres au serveur et obtenir un PDF en réponse. Le serveur utilise Laravel.

Alors

axios.get(`order-results/${id}/export-pdf`, { params: { ... }})

effectue la demande mais ne lance pas le téléchargement forcé, même si le serveur renvoie les en-têtes corrects.

Je pense que c'est une situation typique dans laquelle vous devez, par exemple, créer un rapport PDF et transmettre des filtres au serveur. Alors, comment cela pourrait-il être accompli?

Mettre à jour

Donc, en fait, j'ai trouvé une solution. Cependant, la même approche ne fonctionnait pas avec axios, je ne sais pas pourquoi, c'est pourquoi j'ai utilisé un objet XHR brut. La solution consiste donc à créer un objet blob et une fonction utilisateur createUrlObject. Exemple:

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()
  }
}

Important: vous devez avoir un tampon de tableau comme type de réponse

Cependant, le même code écrit dans axios renvoie PDF qui est vide:

axios.post(`order-results/${id}/export-pdf`, {
  data,
  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
})
25
Victor

Vous obtenez PDF vide car aucune donnée n'est transmise au serveur. Vous pouvez essayer de transmettre des données en utilisant un objet de données comme celui-ci.

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

En passant, je vous remercie beaucoup de m'avoir montré cette astuce pour pouvoir télécharger le pdf à partir de la réponse. Merci à toi :)

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

La façon dont j'ai utilisé est,

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()
})

42
Roshimon

Essayez ceci: Cela fonctionne parfaitement pour moi avec la compatibilité pour Internet Explorer 11 (createObjectURL ne fonctionne pas sur Explorer 11)

axios({
  url: 'http://vvv.dev',
  method: 'GET',
  responseType: 'blob', // important
}).then((response) => {
  if (!window.navigator.msSaveOrOpenBlob){
    // BLOB NAVIGATOR
    const url = window.URL.createObjectURL(new Blob([response.data]));
    const link = document.createElement('a');
    link.href = url;
    link.setAttribute('download', 'download.pdf');
    document.body.appendChild(link);
    link.click();
  }else{
    // BLOB FOR Explorer 11
    const url = window.navigator.msSaveOrOpenBlob(new Blob([response.data]),"download.pdf");
  }
});

https://Gist.github.com/javilobo8/097c30a233786be52070986d8cdb1743

8
gtamborero

Je ne pense pas que ce soit possible de le faire dans axios ou même AJAX. Le fichier sera conservé en mémoire, c’est-à-dire que vous ne pourrez pas enregistrer le fichier sur le disque. En effet, JavaScript ne peut pas interagir avec le disque. Ce serait un grave problème de sécurité et il est bloqué dans tous les principaux navigateurs. 

Vous pouvez construire votre URL en frontal et le télécharger de la manière suivante:

 var url = 'http://example.com/order-results/' + id + '/export-pdf?' + '..params..' 

 window.open(url, '_blank');

J'espère que cela t'aides!

3
Deepak

J'ai essayé certaines des approches suggérées ci-dessus, mais dans mon cas, le navigateur m'envoyait l'avertissement de blocage du bloc de fenêtres contextuelles .

axios.get(url, {responseType: 'arraybuffer'})
   .then(function (response) {
     var headers = response.headers();
     var blob = new Blob([response.data],{type:headers['content-type']});
     var link = document.createElement('a');
     link.href = window.URL.createObjectURL(blob);
     link.download = "Your_file_name";
     link.click();
});
0
Bruno Soares

J'ai eu des problèmes similaires - j'ai fini par créer un lien et télécharger à partir de là.

J'ai mis plus de détails sur la façon dont answer sur une autre question de stackoverflow.

0
Anthony