使用 axios 强制下载 GET 请求

IT技术 javascript vue.js vuejs2 axios
2021-03-10 15:58:41

我正在使用 vuejs 2 + axios。我需要发送一个获取请求,将一些参数传递给服务器,然后获取一个 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
})
6个回答

您得到的是空的 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()
})

就目前而言,这很好用。现在,如何使用来自服务器的文件名? content-disposition: attachment; filename="My Test - Doc Title.pdf"
2021-04-30 15:58:41
很好的解决方案。我已经放了responseType:'blob'并且 response.data 直接包含了 blob。
2021-05-16 15:58:41
我得到了Uncaught (in promise) Error: Request failed with status code 500,我该如何解决这个问题?
2021-05-18 15:58:41

试试这个:它与 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

responseType: 'blob'是关键部分!谢谢
2021-04-23 15:58:41

我认为在 axios 甚至 AJAX 中都不可能做到这一点。该文件将保存在内存中,即您不能将文件保存到磁盘。这是因为 JavaScript 无法与磁盘交互。这将是一个严重的安全问题,并且在所有主要浏览器中都被阻止。

您可以在前端构建您的 URL 并通过以下方式下载它:

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

 window.open(url, '_blank');

希望这可以帮助!

如果我需要发送 post 请求怎么办?因为可能请求参数对于 get 来说太大了
2021-04-25 15:58:41
无论如何,您都无法将文件保存到磁盘。GET 请求可以允许 2048 个字符。
2021-05-08 15:58:41

我尝试了一些上述建议的方法,但在我的情况下,浏览器向我发送了弹出块警告。下面描述的代码对我有用:

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

这段代码对我有用:

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

}