Vue Laravel:如何正确下载 PDF 文件?

新手上路,请多包涵

情况:

前端:Vue。后端:Laravel。

在网络应用程序中,我需要让用户下载某些 pdf 文件:

  • 我需要 Laravel 获取文件并将其作为 API GET 请求的响应返回。
  • 然后在我的 Vue 网络应用程序中,我需要获取文件并下载它。

编码:

接口:

 $file = public_path() . "/path/test.pdf";

$headers = [
    'Content-Type' => 'application/pdf',
];
return response()->download($file, 'test.pdf', $headers);

网络应用:

 downloadFile() {
  this.$http.get(this.apiPath + '/download_pdf')
    .then(response => {
      let blob = new Blob([response.data], { type: 'application/pdf' })
      let link = document.createElement('a')
      link.href = window.URL.createObjectURL(blob)
      link.download = 'test.pdf'
      link.click()
    })
}

结果:

使用此代码,我确实设法下载了一个 pdf 文件。问题是pdf是空白的。

不知何故,数据被破坏了(不是这个特定的 pdf 文件的问题,我尝试了几个 pdf 文件 - 结果相同)

来自服务器的响应:

来自服务器的响应本身很好:

在此处输入图像描述

PDF:

问题可能出在pdf文件上。它看起来肯定是损坏的数据。这是 response.data 外观的摘录:

在此处输入图像描述

问题:

如何使用 Laravel for API 和 Vue for the web app 正确下载 pdf 文件?

谢谢!

原文由 FrancescoMussi 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 855
2 个回答

解决方案:

上面的代码是正确的。缺少的是添加正确的 responseType 作为 arraybuffer

我被响应中的那些 ???? 吓到了,这误导了我。这些问号没问题,因为 pdf 是二进制数据,应该由适当的读者阅读。

阵列缓冲区:

而arraybuffer正是用来保存二进制数据。

这是来自 Mozilla 网站的定义:

ArrayBuffer 对象用于表示一个通用的、固定长度的原始二进制数据缓冲区。您不能直接操作 ArrayBuffer 的内容;相反,您创建一个类型化的数组对象或 DataView 对象,它以特定格式表示缓冲区,并使用它来读取和写入缓冲区的内容。

ResponseType 字符串表示响应的类型。通过告诉它一个数组缓冲区,它会相应地处理数据。

只需添加 responseType,我就可以正确下载 pdf 文件。

编码:

这是更正后的 Vue 代码(与以前完全相同,但添加了 responseType):

 downloadFile() {
  this.$http.get(this.appApiPath + '/testpdf', {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 = 'test.pdf'
      link.click()
    })
}

编辑:

这是一个更完整的解决方案,它考虑了其他浏览器的行为:

 downloadContract(booking) {
  this.$http.get(this.appApiPath + '/download_contract/' + booking.id, {responseType: 'arraybuffer'})
    .then(response => {
      this.downloadFile(response, 'customFilename')
    }, response => {
      console.warn('error from download_contract')
      console.log(response)
      // Manage errors
      }
    })
},

downloadFile(response, filename) {
  // It is necessary to create a new blob object with mime-type explicitly set
  // otherwise only Chrome works like it should
  var newBlob = new Blob([response.body], {type: 'application/pdf'})

  // IE doesn't allow using a blob object directly as link href
  // instead it is necessary to use msSaveOrOpenBlob
  if (window.navigator && window.navigator.msSaveOrOpenBlob) {
    window.navigator.msSaveOrOpenBlob(newBlob)
    return
  }

  // For other browsers:
  // Create a link pointing to the ObjectURL containing the blob.
  const data = window.URL.createObjectURL(newBlob)
  var link = document.createElement('a')
  link.href = data
  link.download = filename + '.pdf'
  link.click()
  setTimeout(function () {
    // For Firefox it is necessary to delay revoking the ObjectURL
    window.URL.revokeObjectURL(data)
  }, 100)
},

原文由 FrancescoMussi 发布,翻译遵循 CC BY-SA 4.0 许可协议

您将无法从 Laravel 下载到 Vue 因为两者都在我假设的不同端口上运行。

即使你尝试这样的事情。

 public function getDownload()
    {
        //PDF file is stored under project/public/download/info.pdf
        $file= public_path(). "/download/info.pdf";

        $headers = [
              'Content-Type' => 'application/pdf',
           ];

    return response()->download($file, 'filename.pdf', $headers);
    }

当您将标头发送到 Laravel 端口尝试使用 Vue js 库并尝试在库中发送该 pdf 内容时,这无济于事

试试这个 从这里获得帮助

原文由 Sagar Ahuja 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题