You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

后端返回PDF下载后显示空白页问题排查求助

下载PDF空白问题排查与解决

问题描述

处理后端发送的PDF下载时,获取Blob响应后,下载的PDF页数和预期一致,但所有页面都是空白。发现后端返回的PDF用记事本打开显示为UTF-8格式,而本地正常PDF显示为ANSI格式,需要确认是否是编码或代码问题。


相关截图

后端响应预览

后端响应预览

请求头与数据详情

请求头与数据详情

空白PDF页面效果

空白PDF页面效果

记事本打开的PDF内容

记事本打开的PDF内容


相关代码

前端下载代码

const receipt = await this.downloadBookingReceipt({
  bookingNumber: this.bus.bookingReference,
  receiptFormat: 'pdf',
});

/**
 * 使用 file-saver 库
 */
const blob = new Blob([receipt.data], { type: 'application/pdf' });
saveAs(blob, 'receipt.pdf', { autoBom: true });

/**
 * 使用 <a> 标签
 */
const pdfData = new Blob([receipt], { type: 'application/pdf' });
// 创建指向Blob对象URL的链接
const pdfUrl = window.URL.createObjectURL(pdfData);
const downloadLink = document.createElement('a');
downloadLink.href = pdfUrl;
downloadLink.download = `${this.bus.bookingReference}-receipt.pdf`;
downloadLink.click();
setTimeout(function () {
  // Firefox需要延迟撤销ObjectURL
  window.URL.revokeObjectURL(pdfUrl);
}, 100);

downloadBookingReceipt 请求函数

static async downloadBookingReceipt (axios, { bookingNumber, receiptFormat }) {
  return await axios.get(
    `/v1/booking/${bookingNumber}/receipt/${receiptFormat}`, {
      responseType: 'blob',
    }
  );
}

后端接口处理代码

/**
 * 预订收据处理逻辑
 */
const { data } = await axios.get(BASE_URL + req._parsedUrl.path, {
  headers: {
    AccessToken: TOKEN,
  },
});
res.setHeader(
  'content-disposition',
  `attachment; filename=&quot;${req.url.slice(9, 18)}-receipt.pdf&quot;`
);
res.setHeader('Content-Type', 'application/pdf');
res.end(data);
/** */

问题原因与修复方案

核心问题

后端转发第三方PDF接口时,未指定响应类型为二进制流,导致axios默认把返回的PDF二进制数据解析成了UTF-8编码的字符串。后续转成Blob时,原始二进制内容被损坏,最终打开的PDF就是空白页。

修复步骤

  1. 后端修改:调用第三方接口时添加responseType: 'arraybuffer',确保拿到原始二进制数据:
const { data } = await axios.get(BASE_URL + req._parsedUrl.path, {
  headers: {
    AccessToken: TOKEN,
  },
  responseType: 'arraybuffer' // 新增该行
});

这样后端获取的data是二进制数组,而非UTF-8字符串,转发给前端时不会损坏内容。

  1. 前端优化:
    • <a>标签下载的代码中,错误地将整个receipt响应对象传入Blob,要和file-saver写法一致,使用receipt.data:
      // 原错误代码
      const pdfData = new Blob([receipt], { type: 'application/pdf' });
      // 修正后
      const pdfData = new Blob([receipt.data], { type: 'application/pdf' });
      
    • PDF是二进制文件,不需要开启autoBom: true,建议移除该选项避免自动添加BOM头损坏文件:
      saveAs(blob, 'receipt.pdf'); // 移除autoBom参数
      

编码说明

PDF本身是二进制格式,不存在UTF-8或ANSI的说法。记事本显示的编码差异,是因为它把损坏的二进制内容当成文本解析时的编码猜测,核心问题还是二进制数据被错误转换成了字符串。

内容的提问来源于stack exchange,提问作者DarkPo13

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 15:47:15