【问题标题】:Creating PDF from request response doesn't work with axios but works in native xhr从请求响应创建 PDF 不适用于 axios,但适用于本机 xhr
【发布时间】:2017-09-27 02:07:33
【问题描述】:

为了强制从服务器下载 PDF,我尝试使用 axios 和本机 xhr 对象。原因是我必须发送 post 请求,因为我向服务器传递了太多数据,所以带有简单链接的选项(如 site.ru/download-pdf 对我不起作用)。

即使我最终设法用 Xhr 做到了这一点,我仍然不知道为什么 axios 方式不起作用。

这是我使用 xhr 执行此操作的方法,它适用于我:

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

    xhr.send("data=" + data);

这是“axios-way”,我实际上得到了页数正确的 PDF,但它们都是空的:

    axios.post(`order-results/${id}/export-pdf`, {
      data,
      responseType: 'arraybuffer'
    }).then((response) => {
      let blob = new Blob([response.data], { type:"application/pdf" })
      let link = document.createElement('a')
      link.href = window.URL.createObjectURL(blob)
      link.download = 'Results.pdf'
      link.click()
    })

Axios 已配置为发送授权令牌。 我将Application/x-www-form-urlencoded 放在 xhr 中,否则我无法在服务器端获取数据。

即使 xhr 有效,我还是更喜欢使用 axios,因为我到处都在使用它,而且我只是好奇我做错了什么。我尝试了不同的解决方案,只有原生 xhr 完成了这项工作。

【问题讨论】:

标签: javascript ajax pdf xmlhttprequest axios


【解决方案1】:

以下对我有用:

axios.post("http://localhost:8080/reports/my-report/",
        data,
        {
            responseType: 'arraybuffer',
            headers: {
                'Content-Type': 'application/json',
                'Accept': 'application/pdf'
            }
        })
        .then((response) => {
            const url = window.URL.createObjectURL(new Blob([response.data]));
            const link = document.createElement('a');
            link.href = url;
            link.setAttribute('download', 'file.pdf'); //or any other extension
            document.body.appendChild(link);
            link.click();
        })
        .catch((error) => console.log(error));

如果这有帮助,请告诉我。

干杯!

【讨论】:

  • 它有效。我在请求配置中想念responseType: 'arraybuffer'
  • 这很好用,就目前而言。现在,如何使用来自服务器的文件名? content-disposition: attachment; filename="My Test - Doc Title.pdf"
  • responseType: 'arraybuffer' 做了什么让它如此重要?
  • 这真的很有帮助。谢谢
【解决方案2】:

无论出于何种原因,pdf 正在下载,但传递的任何内容都没有出现,从而导致空白 pdf。

我发现此代码 sn-p 相似,但会生成包含内容的 pdf。

 axios({
                url: '/pdf',
                method: 'GET',
                responseType: 'blob', // important
            }).then((response) => {
                const url = window.URL.createObjectURL(new Blob([response.data]));
                const link = document.createElement('a');
                link.href = url;
                link.setAttribute('download', 'file.pdf');
                document.body.appendChild(link);
                link.click();
            });

有一些反馈说它在 IE 11 上不起作用,我没有对其进行测试,但使用 FileSaver.js 发布了解决方案

axios({
            url: '/pdf',
            method: 'GET',
            responseType: 'blob', // important
        }).then((response) => {
            FileSaver.saveAs(new Blob([response.data]));
        });

【讨论】:

  • 这是一个 get 请求,它返回显示正常的 pdf,但 post 请求似乎会影响响应数据,从而导致空白 pdf
【解决方案3】:

有一个特殊的responseType:'blob':

axios.post(`order-results/${id}/export-pdf`, {
  data,
  responseType: 'blob'
}).then((response) => {
  let link = window.URL.createObjectURL(blob)
  link.download = 'Results.pdf'
  link.click()
})

或者你可以使用window.open方法:

axios.post(`order-results/${id}/export-pdf`, {
  data,
  responseType: 'blob'
}).then((response) => {
  window.open(URL.createObjectURL(response.data));
})

【讨论】:

    【解决方案4】:

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

    【讨论】:

    • 哦,对不起那个伙伴。
    猜你喜欢
    • 2020-06-13
    • 1970-01-01
    • 2020-07-19
    • 2019-04-11
    • 2018-06-22
    • 2018-11-21
    • 1970-01-01
    • 1970-01-01
    • 2021-12-15
    相关资源
    最近更新 更多