Laravel+Vue.js中Axios下载DomPdf生成的PDF为空问题求助
解决Laravel + Axios下载空白PDF的问题
我之前也碰到过一模一样的情况——用Axios请求DomPdf生成的PDF时,下载下来的文件全是空白,但直接访问路由却完全正常。结合你的代码,我来帮你分析问题并给出可行的修复方案。
我的问题重现(和你的情况一致)
Laravel 后端代码
return PDF::loadView('print', compact('bill'))->download($bill->number.'.pdf');
JavaScript (Axios + download.js) 代码
axios.get(`/bills/${id}/print`, { responseType: 'blob',Accept: 'application/pdf' }) .then(response => { const download = require('@/download'); // @ 是根js目录的别名 download(response.data, `file.pdf`, 'application/pdf'); });
问题根源
当你用Laravel的download()方法返回响应时,框架会自动添加Content-Disposition: attachment; filename="xxx.pdf"响应头,这个头是给浏览器用来触发原生下载弹窗的。但通过Ajax请求时,浏览器不会自动处理这个头,而且download()返回的响应格式和Axios处理Blob数据的逻辑不兼容,导致二进制数据解析出错,最终生成空白PDF。
修复方案
1. 后端调整:返回PDF的原始二进制内容
把后端的download()换成output(),手动设置响应头,这样返回的是纯PDF二进制数据,方便前端正确处理:
$pdf = PDF::loadView('print', compact('bill')); return response($pdf->output(), 200, [ 'Content-Type' => 'application/pdf', 'Content-Disposition' => 'inline; filename="'.$bill->number.'.pdf"', // 要让前端能读取文件名,必须添加这个头暴露Content-Disposition 'Access-Control-Expose-Headers' => 'Content-Disposition' ]);
2. 前端优化:正确处理Blob数据
你可以选择原生JS实现下载(更可靠),或者适配download.js继续使用:
方式一:原生JS实现下载(推荐)
axios.get(`/bills/${id}/print`, { responseType: 'blob' }) .then(response => { // 从响应头提取后端返回的文件名 const contentDisposition = response.headers['content-disposition']; const filename = contentDisposition.match(/filename="(.+)"/)[1]; // 创建Blob对象和临时下载链接 const blob = new Blob([response.data], { type: 'application/pdf' }); const url = window.URL.createObjectURL(blob); const link = document.createElement('a'); link.href = url; link.download = filename; document.body.appendChild(link); link.click(); // 清理临时资源,避免内存泄漏 window.URL.revokeObjectURL(url); document.body.removeChild(link); }) .catch(err => console.error('PDF下载失败:', err));
方式二:适配download.js
axios.get(`/bills/${id}/print`, { responseType: 'blob' }) .then(response => { const download = require('@/download'); const contentDisposition = response.headers['content-disposition']; const filename = contentDisposition.match(/filename="(.+)"/)[1]; // 确保传入download.js的是正确的Blob对象 const blob = new Blob([response.data], { type: 'application/pdf' }); download(blob, filename, 'application/pdf'); });
额外检查点
- 先直接访问
/bills/{id}/print路由,确认DomPdf生成的PDF本身是有内容的,排除后端生成环节的问题。 - 如果是跨域请求,确保后端的CORS配置允许
Access-Control-Expose-Headers,否则前端读不到Content-Disposition头。
内容的提问来源于stack exchange,提问作者Saud Qureshi
相关产品推荐
相关产品推荐

