简体   繁体   English

使用 axios 强制下载 GET 请求

[英]Force download GET request using axios

I'm using vuejs 2 + axios.我正在使用 vuejs 2 + axios。 I need to send a get request, pass some params to server, and get a PDF as a response.我需要发送一个 get 请求,将一些参数传递给服务器,并获得一个 PDF 作为响应。 Server uses Laravel.服务器使用 Laravel。

So所以

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

makes successful request but it does not start force downloading, even though server returns correct headers.发出成功的请求,但它不会开始强制下载,即使服务器返回正确的标头。

I think this is a typical situation when you need to, say, form a PDF report and pass some filters to server.我认为这是一种典型的情况,例如,您需要形成 PDF 报告并将一些过滤器传递给服务器。 So how could it be accomplished?那怎么可能实现呢?

Update更新

So actually I found a solution.所以实际上我找到了一个解决方案。 However the same approach didn't work with axios, don't know why, that's why I used raw XHR object.但是同样的方法不适用于 axios,不知道为什么,这就是我使用原始 XHR 对象的原因。 So the solution is to create a blob object and user createUrlObject function.所以解决方案是创建一个blob对象和用户createUrlObject函数。 Sample example:示例:

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: you should have array buffer as response type重要提示:您应该将数组缓冲区作为响应类型

However, the same code written in axios returns PDF which is empty:但是,用 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
})

You're getting empty PDF 'cause no data is passed to the server.您得到的是空的 PDF,因为没有数据传递到服务器。 You can try passing data using data object like this您可以尝试使用这样的数据对象传递数据

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

By the way I gotta thank you so much for showing me the hint in order to download pdf from response.顺便说一句,我非常感谢您向我展示提示,以便从回复中下载 pdf。 Thank ya :)谢谢你:)

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

The way in which I have used is,我使用的方式是,

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

Try this: It works perfectly for me with compatibility for Internet Explorer 11 (createObjectURL doesn't work on Explorer 11)试试这个:它与 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 https://gist.github.com/javilobo8/097c30a233786be52070986d8cdb1743

I don't think its possible to do this in axios or even AJAX.我认为在 axios 甚至 AJAX 中都不可能做到这一点。 The file will be kept in memory, ie you cannot save file to disk.该文件将保存在内存中,即您不能将文件保存到磁盘。 This is because JavaScript cannot interact with disk.这是因为 JavaScript 无法与磁盘交互。 That would be a serious security issue and it is blocked in all major browsers.这将是一个严重的安全问题,并且在所有主要浏览器中都被阻止。

You can construct your URL in front-end and download it in the following way:您可以在前端构建您的 URL 并通过以下方式下载它:

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

 window.open(url, '_blank');

Hope this helps!希望这可以帮助!

I tried some of the above suggested approaches but in my case the browser was sending me the popup block warning.我尝试了上述一些建议的方法,但在我的情况下,浏览器向我发送了弹出窗口阻止警告。 The code described below worked for me:下面描述的代码对我有用:

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

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

} }

I had similar issues- I ended up creating link and downloading from there.我遇到了类似的问题 - 我最终创建了链接并从那里下载。

I put more details of how in the answer on another stackoverflow question.我在另一个 stackoverflow 问题的答案中详细说明了如何操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM