Vue + Laravel:如何正确下载 PDF 文件? [英] Vue + Laravel: How to properly download a PDF file?

查看:24
本文介绍了Vue + Laravel:如何正确下载 PDF 文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

情况:

前端:Vue.后端:Laravel.

Frontend: Vue. Backend: Laravel.

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

Inside the web app I need to let the user download certain pdf files:

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

代码:

API:

$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是空白的.

Using this code I do manage to download a pdf file. The problem is that the pdf is blank.

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

Somehow the data got corrupted (not a problem of this particular pdf file, I have tried with several pdf files - same outcome)

来自服务器的响应:

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

The response itself from the server is fine:

PDF:

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

The problem may be with the pdf file. It definitely looks corrupted data. This is an excerpt of how it looks like the response.data:

问题:

如何使用 Laravel 的 API 和 Vue 的 Web 应用程序正确下载 pdf 文件?

How can I properly download a pdf file using Laravel for the API and Vue for the web app?

谢谢!

推荐答案

解决方案:

上面的代码是正确的.缺少的是将正确的 responseType 添加为 arraybuffer.

The code above was correct. What was missing was adding the proper responseType as arraybuffer.

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

I got scared by those ???? inside the response, and that was misleading me. Those question marks were just okay since pdf is a binary data and is meant to be read by a proper reader.

数组缓冲区:

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

And arraybuffer is precisely used to keep binary data.

这是来自 mozilla 网站的定义:

This is the definition from the mozilla website:

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

The ArrayBuffer object is used to represent a generic, fixed-length raw binary data buffer. You cannot directly manipulate the contents of an ArrayBuffer; instead, you create one of the typed array objects or a DataView object which represents the buffer in a specific format, and use that to read and write the contents of the buffer.

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

And the ResponseType string indicates the type of the response. By telling its an arraybuffer, it then treats the data accordingly.

仅仅通过添加 responseType 我就成功地下载了 pdf 文件.

And just by adding the responseType I managed to properly download the pdf file.

代码:

这是更正的 Vue 代码(与之前完全一样,但添加了 responseType):

This is corrected Vue code (exactly as before, but with the addition of the 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()
    })
}

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

This is a more complete solution that take into account other browsers behavior:

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

这篇关于Vue + Laravel:如何正确下载 PDF 文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆