【问题标题】:Download PDF from http response with Axios使用 Axios 从 http 响应下载 PDF
【发布时间】:2019-01-02 00:10:02
【问题描述】:

我正在开发一个带有 Laravel 后端 API 的 Vue 应用程序。单击链接后,我想调用服务器以下载某个文件(大多数情况下是 PDF 文件)。当我使用axios 发出get 请求时,我会在响应正文中得到一个PDF 作为回报。我想直接下载那个文件。

为了让您更好地了解响应的样子:

(注意:我知道真实的文本响应比图像更好,但由于实际 PDF 内容的长度,我看不到任何返回它的方法..)

有什么方法可以使用 JavaScript 或其他方式下载该文件吗?它必须是特定的直接下载,而无需再次单击该按钮。

代码

// This method gets called when clicking on a link
downloadFile(id) {
    const specificationId = this.$route.params.specificationId;

    axios
        .get(`${this.$API_URL}/api/v1/suppliersmanagement/product-specifications/${specificationId}/fileupload/${id}/download`, {
            headers: this.headers,
        })
        .then(response => {
            console.log(response);
            // Direct download the file here..
        })
        .catch(error => console.log(error));
},

【问题讨论】:

  • 看看this link。虽然它在 asp.net 中,但您的服务器代码应该正确设置标题,以便客户端引起提示或显示 pdf。

标签: javascript http vue.js axios


【解决方案1】:

正如@Sandip Nirmal 建议的那样,我使用了downloadjs,结果非常好!不得不对我的代码进行一些调整,但最终成功了。

我的新代码

// npm i downloadjs
import download from 'downloadjs'

// method
downloadFile(file) {
    const specificationId = this.$route.params.specificationId;

    axios
        .get(`${this.$API_URL}/api/v1/suppliersmanagement/product-specifications/${specificationId}/fileupload/${file.id}/download`, {
            headers: this.headers,
            responseType: 'blob', // had to add this one here
        })
        .then(response => {
           const content = response.headers['content-type'];
           download(response.data, file.file_name, content)
        })
        .catch(error => console.log(error));
},

【讨论】:

  • 我还能够使用 downloadjs 使其适用于 PDF。谢谢你的提示。请注意,refereceType: 'blob' 是必需的。
  • 很好的答案,直接工作..谢谢!
  • 使用 arraybuffer 为我解决了这个问题。
【解决方案2】:

您有两种选择。如果您想从服务器执行此操作,并且您使用 Node.js 作为后端。您可以使用res.download 快递方法轻松完成。您可以按照Download a file from NodeJS Server using Express 的答案进行操作。

但是,如果您想从客户端处理它,那么选择很少,因为您不能使用 axios、XHR、fetch 直接下载文件。您可以使用download.js 或按照以下方式编写自己的代码。

return axios({
    url: '/download', // download url
    method: 'get',
    headers: {
      Accept: 'application/json',
      'Content-Type': 'application/json',
      mode: 'no-cors'
    }
  })
    .then(response => response.blob())
    .then(blob => {
      var url = window.URL.createObjectURL(blob)
      var a = document.createElement('a')
      a.href = url
      a.download = fileName
      a.click()
      a.remove()
      setTimeout(() => window.URL.revokeObjectURL(url), 100)
    })

由于服务器返回的响应是json格式,你需要将其转换为ObjectURL并设置为锚标记。

如果你潜入download.js 代码,你会发现相同的实现。

【讨论】:

  • 正如您在我的帖子中看到的,我不使用 Node.js,但我使用 Laravel。无论如何,我会研究 download.js
  • download.js 与上述代码 sn-p 完全相同。
  • response.blob is not a function 。 // - 仅限浏览器:FormData、File、Blob。 // - 仅限节点:流、缓冲区。我正在开发一个 Node JS CLI 工具。我正在尝试使用stream 复制.blob() 方法。
  • 我能够使用data.pipe(writer)writer.on("finish") 监听器来保存文件,然后在我的 CLI 工具中本地提供文件。
【解决方案3】:

您应该使用“responseType”选项。例如:

axios.get(
  url, 
  {responseType: 'blob'} // !!!
).then((response) => {
  window.open(URL.createObjectURL(response.data));
})

【讨论】:

  • 就是这样!为了正确接收来自服务器的 pdf,我必须在 httpService 调用的配置字段中使用 responseType: 'arraybuffer'。谢谢!
【解决方案4】:

你可以这样做

download(filename) {
  fetch(url , { headers })
  .then(response => response.blob())
  .then(blob => URL.createObjectURL(blob))
  .then(uril => {
    var link = document.createElement("a");
    link.href = uril;
    link.download = filename + ".csv";
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
  });
}

这里我想下载一个 CSV 文件,所以我在文件名中添加了 .csv。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-26
    • 2014-07-30
    • 1970-01-01
    • 1970-01-01
    • 2018-09-19
    • 2021-09-01
    • 2019-03-23
    • 1970-01-01
    相关资源
    最近更新 更多