axiosを使った強制ダウンロードGETリクエスト

vuejs 2 + axiosを使っています。 getリクエストを送信し、いくつかのパラメータをサーバーに渡し、レスポンスとしてPDFを取得する必要があります。サーバーはLaravelを使用しています。

そこで

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

はリクエストに成功しましたが、サーバーが正しいヘッダを返したにもかかわらず、強制ダウンロードを開始しませんでした。

これは、例えばPDFレポートを作成し、いくつかのフィルタをサーバに渡す必要がある場合の典型的な状況だと思います。では、どうすれば実現できるのでしょうか?

**更新

実は解決策を見つけました。しかし、同じ方法はaxiosではうまくいかなかった。そこで、blobオブジェクトを作成して、createUrlObject関数を使用することで解決しました。サンプル例:

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

**重要:レスポンスタイプとして配列バッファを指定する必要があります。

しかし、axiosで同じコードを書くと、空のPDFが返されます:

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
})
質問へのコメント (5)
ソリューション

サーバにデータが渡されていないため、空のPDFが表示されています。次のようにデータオブジェクトを使ってデータを渡してみてください。

解説 (2)

これを試して: Internet Explorer 11との互換性により、私にとっては完全に機能します(createObjectURLは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

解説 (0)

アクシオスやAJAXでこれを行うことは不可能だと思います。ファイルはメモリ上に保存されます。つまり、ファイルをディスクに保存することはできません。JavaScriptはディスクとやりとりできないからです。これは重大なセキュリティ問題であり、すべての主要なブラウザでブロックされています。

フロントエンドでURLを作成し、以下の方法でダウンロードすることができます:

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

 window.open(url, '_blank');

お役に立てれば幸いです!

解説 (2)

上記の提案されたアプローチのいくつかを試しましたが、私の場合、ブラウザからポップアップブロック警告が送信されました。 以下で説明するコードは私のために機能しました:

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)

結局、リンクを作成してそこからダウンロードした。

スタックオーバーフローの別の質問のanswerにその方法の詳細を書きました。

解説 (0)