Vue.js从二进制代码保存PDF失败:空文件问题排查
问题排查与解决方案
核心问题分析
从你的响应数据能看到两个关键问题:
- 后端返回的
content-type是application/json; charset=UTF-8,而非预期的application/pdf,说明后端是把PDF内容以字符串形式包裹在JSON里返回,不是直接输出二进制PDF流。 - 请求头里添加了多余字段:
content-type、content-disposition、content-transfer-encoding都是响应头字段,在请求里设置完全无效,反而可能干扰后端处理。
代码修正步骤
1. 精简请求配置
去掉请求头里不必要的字段,只保留声明接受PDF的Accept头:
axios.get(process.env.VUE_APP_PUBLIC_API + '/preview-my-bill?id=123456', { responseType: 'text', // 先以文本形式接收JSON里的PDF字符串 headers: { 'Accept': 'application/pdf' } } )
2. 正确转换PDF字符串为Blob
后端返回的JSON中data字段是带%PDF-1.4开头的原始PDF字符串,需要将其转换为二进制数组后再生成Blob:
.then(res => { // 若后端返回的是完整JSON对象,先提取PDF字符串(比如res.data.pdfContent) const pdfString = res.data; // 将字符串转换为Uint8Array二进制数组 const uint8Array = new TextEncoder().encode(pdfString); // 生成正确的PDF格式Blob const blob = new Blob([uint8Array], { type: "application/pdf" }); // 后续下载逻辑保持不变 var downloadLink = document.createElement('a'); downloadLink.target = '_blank'; downloadLink.download = 'test.pdf'; const downloadUrl = URL.createObjectURL(blob); this.PreviewInvoice = downloadUrl; downloadLink.href = downloadUrl; document.body.append(downloadLink); downloadLink.click(); document.body.removeChild(downloadLink); URL.revokeObjectURL(downloadUrl); })
3. 后端侧验证(关键)
如果前端修改后仍无效,必须确认后端输出逻辑:
- 后端应直接返回二进制PDF数据,而非将PDF转成字符串包在JSON中。
- 后端响应头必须设置
Content-Type: application/pdf,如需触发下载可额外添加Content-Disposition: attachment; filename="invoice.pdf"。
特殊情况处理
若后端返回的是Base64编码的PDF字符串(开头为data:application/pdf;base64,),需先解码再转换:
// 去掉Base64前缀(如果存在) const base64String = pdfString.replace(/^data:application\/pdf;base64,/, ''); // 解码为Uint8Array const uint8Array = Uint8Array.from(atob(base64String), c => c.charCodeAt(0)); const blob = new Blob([uint8Array], { type: "application/pdf" });
内容的提问来源于stack exchange,提问作者amjad khalil
相关产品推荐
相关产品推荐

