Vue + Laravel:如何正确下载 PDF 文件?
Vue + Laravel: How to properly download a PDF file?
情况:
前端:Vue。后端:Laravel.
在网络应用程序中,我需要让用户下载某些 pdf 文件:
- 我需要 Laravel 获取文件并 return 它作为 API GET 请求的响应。
- 然后在我的 Vue 网络应用程序中,我需要获取文件并下载它。
代码:
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是空白的。
数据以某种方式损坏(不是这个特定 pdf 文件的问题,我尝试了几个 pdf 文件 - 结果相同)
来自服务器的响应:
服务器本身的响应正常:
PDF:
问题可能出在 pdf 文件上。它看起来绝对是损坏的数据。这是 response.data
:
的摘录
问题:
如何使用 Laravel 为 API 和 Vue 为网络应用程序正确下载 pdf 文件?
谢谢!
您将无法从 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);
}
它不会帮助你发送 headers 到 Laravel
端口尝试使用 Vue js
库并尝试在库
上发送该 pdf 内容
试试这个
Get help from here
解决方案:
上面的代码是正确的。缺少的是添加正确的 responseType
作为 arraybuffer
.
我被回复中的 ????
吓到了,那误导了我。
这些问号没问题,因为 pdf 是二进制数据,应该由适当的 reader.
读取
数组缓冲区:
而arraybuffer正是用来保存二进制数据的。
这是mozilla网站上的定义:
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
字符串表示响应的类型。通过告诉它一个数组缓冲区,它会相应地处理数据。
通过添加 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)
},
downloadFile: function () {
this.$http.post('{{ route('download.download') }}', {
_token: "{{ csrf_token() }}",
inputs: this.inputs
},{responseType: 'arraybuffer'}).then(response => {
var filename = response.headers.get('content-disposition').split('=')[1].replace(/^\"+|\"+$/g, '')
var url = window.URL.createObjectURL(new Blob([response.body],{type:response.headers.get('content-type')}))
var link = document.createElement('a')
link.href = url
link.setAttribute('download', filename)
document.body.appendChild(link)
link.click()
});
},
对我有用。
来自 laravel 后端:
$pdf = PDF::loadView('your_view_name', ['data' => $data]);
return $pdf->output();
来自 vuejs 前端:
axios({
url: 'http://localhost:8000/api/your-route',
method: 'GET',
responseType: 'blob',
}).then((response) => {
var fileURL = window.URL.createObjectURL(new Blob([response.data]));
var fileLink = document.createElement('a');
fileLink.href = fileURL;
fileLink.setAttribute('download', 'file.pdf');
document.body.appendChild(fileLink);
fileLink.click();
});
情况:
前端:Vue。后端:Laravel.
在网络应用程序中,我需要让用户下载某些 pdf 文件:
- 我需要 Laravel 获取文件并 return 它作为 API GET 请求的响应。
- 然后在我的 Vue 网络应用程序中,我需要获取文件并下载它。
代码:
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是空白的。
数据以某种方式损坏(不是这个特定 pdf 文件的问题,我尝试了几个 pdf 文件 - 结果相同)
来自服务器的响应:
服务器本身的响应正常:
PDF:
问题可能出在 pdf 文件上。它看起来绝对是损坏的数据。这是 response.data
:
问题:
如何使用 Laravel 为 API 和 Vue 为网络应用程序正确下载 pdf 文件?
谢谢!
您将无法从 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);
}
它不会帮助你发送 headers 到 Laravel
端口尝试使用 Vue js
库并尝试在库
试试这个 Get help from here
解决方案:
上面的代码是正确的。缺少的是添加正确的 responseType
作为 arraybuffer
.
我被回复中的 ????
吓到了,那误导了我。
这些问号没问题,因为 pdf 是二进制数据,应该由适当的 reader.
数组缓冲区:
而arraybuffer正是用来保存二进制数据的。
这是mozilla网站上的定义:
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
字符串表示响应的类型。通过告诉它一个数组缓冲区,它会相应地处理数据。
通过添加 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)
},
downloadFile: function () {
this.$http.post('{{ route('download.download') }}', {
_token: "{{ csrf_token() }}",
inputs: this.inputs
},{responseType: 'arraybuffer'}).then(response => {
var filename = response.headers.get('content-disposition').split('=')[1].replace(/^\"+|\"+$/g, '')
var url = window.URL.createObjectURL(new Blob([response.body],{type:response.headers.get('content-type')}))
var link = document.createElement('a')
link.href = url
link.setAttribute('download', filename)
document.body.appendChild(link)
link.click()
});
},
对我有用。
来自 laravel 后端:
$pdf = PDF::loadView('your_view_name', ['data' => $data]);
return $pdf->output();
来自 vuejs 前端:
axios({
url: 'http://localhost:8000/api/your-route',
method: 'GET',
responseType: 'blob',
}).then((response) => {
var fileURL = window.URL.createObjectURL(new Blob([response.data]));
var fileLink = document.createElement('a');
fileLink.href = fileURL;
fileLink.setAttribute('download', 'file.pdf');
document.body.appendChild(fileLink);
fileLink.click();
});