web-dev-qa-db-ja.com

axiosを使用してGETリクエストを強制的にダウンロードする

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

そう

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

リクエストは成功しますが、サーバーが正しいヘッダーを返しても、強制ダウンロードは開始されません。

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

更新

それで実際に解決策を見つけました。ただし、同じアプローチはaxiosで機能しませんでした。理由はわかりません。そのため、生のXHRオブジェクトを使用しました。解決策は、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
})
30
Victor

サーバーにデータが渡されないため、空のPDF 'になります。このようなデータオブジェクトを使用してデータを渡すことができます

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

ちなみに、回答からpdfをダウンロードするためのヒントを見せてくれてありがとう。ありがとうございます:)

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

私が使用した方法は、

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

これを試してください: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/097c30a233786be52070986d8cdb174

9
gtamborero

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

フロントエンドでURLを作成し、次の方法でダウンロードできます。

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

 window.open(url, '_blank');

お役に立てれば!

4
Deepak

上記の方法をいくつか試しましたが、私の場合、ブラウザからポップアップブロックの警告が送られてきました。以下に説明するコードは私のために働いた:

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();
});
1
Bruno Soares

同様の問題がありました。リンクを作成してそこからダウンロードしました。

別のstackoverflowの質問の answer に方法の詳細を記載します。

0
Anthony