使用 Axios 从 http 响应下载 PDF

Posted

技术标签:

【中文标题】使用 Axios 从 http 响应下载 PDF【英文标题】:Download PDF from http response with Axios 【发布时间】: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。 【参考方案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。

【讨论】:

以上是关于使用 Axios 从 http 响应下载 PDF的主要内容,如果未能解决你的问题,请参考以下文章

从请求响应创建 PDF 不适用于 axios,但适用于本机 xhr

无法通过 Vue.js(Axios 帖子)从 Laravel 后端下载文件(pdf)

如何在没有任何 vue 库的情况下在 vue 回调中获取 http 响应标头(axios)

axios和ajax区别

Axios介绍和使用

axios的使用