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

React应用中浏览器无法加载PDF文档问题求助

问题修复:流式PDF传输后浏览器无法加载的解决方法

核心问题排查

导致PDF加载失败的常见原因包括:

  • 后端未正确设置PDF响应头,浏览器无法识别内容类型
  • 转发第三方API响应时丢失关键头信息(如Content-Type)
  • 流式传输过程中未处理第三方API的错误响应
  • 客户端重复包裹Blob导致数据格式异常

1. 后端代码修复

完善路由处理与响应头传递

首先确保Express路由正确解析请求体,并设置必要的PDF响应头:

// Express路由示例
router.post('/api/report', async (req, res) => {
  const { issueId } = req.body;
  if (!issueId) return res.status(400).send('缺少issueId参数');

  // 预设PDF响应头
  res.setHeader('Content-Type', 'application/pdf');

  try {
    await streamIssueReport(issueId, res);
  } catch (err) {
    res.status(500).send('获取报告失败');
    console.error('PDF流错误:', err);
  }
});

优化流式转发函数

修改StreamResponse,添加错误状态码检查并传递第三方API的响应头:

import https from 'https';
import { Writable } from 'stream';

function StreamResponse(
  destination: Writable,
  options: string | https.RequestOptions,
): Promise<void> {
  return new Promise((resolve, reject) => {
    const req = https.request(options, (resp) => {
      // 检查第三方API响应状态
      if (resp.statusCode !== 200) {
        reject(new Error(`第三方API返回错误状态: ${resp.statusCode}`));
        req.abort();
        return;
      }

      // 传递第三方API的响应头
      if (resp.headers['content-type']) {
        (destination as any).setHeader('Content-Type', resp.headers['content-type']);
      }
      if (resp.headers['content-length']) {
        (destination as any).setHeader('Content-Length', resp.headers['content-length']);
      }

      resp.pipe(destination);
      resp.on('end', resolve);
      resp.on('error', reject);
    });

    req.on('error', reject);
    req.end();
  });
}

更新streamIssueReport函数

改为返回Promise以便路由捕获错误:

async streamIssueReport(issueId: string, dest: Writable) {
  const mainUrl = new URL(`${process.env.ISSUE_API_URL}`);
  const httpOptions: https.RequestOptions = {
    method: 'GET',
    hostname: mainUrl.hostname,
    path: `/api/v2/issue/${issueId}/report`,
    headers: {
      Authorization: `Bearer ${process.env.AUTH_TOKEN}`,
    },
  };
  await StreamResponse(dest, httpOptions);
}

2. 客户端代码优化

避免重复包裹Blob,添加响应格式校验:

Axios.post(
  "/api/report",
  { issueId },
  { responseType: "blob" }
)
.then((resp) => {
  // 校验响应类型
  const contentType = resp.headers['content-type'];
  if (!contentType?.includes('application/pdf')) {
    throw new Error('收到非PDF格式响应');
  }

  // 直接使用axios返回的Blob对象
  const fileURL = URL.createObjectURL(resp.data);
  const newTab = window.open(fileURL);

  // 加载完成后释放URL对象,避免内存泄漏
  if (newTab) {
    newTab.addEventListener('load', () => {
      URL.revokeObjectURL(fileURL);
    });
  }
})
.catch((err) => {
  console.error('PDF加载失败:', err);
  alert('无法加载PDF,请检查参数或稍后重试');
});

调试建议

  1. 用Postman直接请求后端/api/report接口,下载响应文件确认是否为有效PDF
  2. 查看浏览器网络请求的响应头,确认Content-Type为application/pdf
  3. 验证第三方API的AUTH_TOKEN有效性及issueId是否存在

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 10:55:12