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

React应用中如何渲染通过Express后端代理获取的PDF内容

React应用中如何渲染通过Express后端代理获取的PDF内容

兄弟,我懂你现在的困境——通过Express代理拿到PDF后,React里用object标签死活渲染不出来,连替代文本都没显示。别着急,咱们先从后端的问题入手,再解决前端的渲染方式,一步步搞定。

第一步:修复Express后端的PDF获取逻辑

你当前的后端代码有个关键问题:axios默认会把响应解析成JSON格式,但PDF是二进制数据,直接这么处理会把数据搞乱,导致前端拿到的是损坏的内容。必须给axios请求加上responseType: 'arraybuffer',确保拿到原始的二进制PDF数据。

修改后的后端代码:

router.get('/fetch-pdf-content', async (req, res) => {
  try {
    // 核心:设置responseType为arraybuffer,保留PDF的二进制结构
    const { data } = await axios.get('https://abc.pdf', {
      responseType: 'arraybuffer'
    });
    res.contentType('application/pdf');
    // 把二进制数据转成Buffer发送给前端
    res.send(Buffer.from(data));
  } catch (error) {
    console.error(error);
    res.status(500).send(error.code || '获取PDF失败');
  }
})

第二步:前端渲染PDF的两种可靠方式

后端修复后,前端就可以用更稳定的方式渲染PDF了,这里给你两种方案:

方案一:用Blob URL配合object/iframe(简单直接)

直接用后端URL有时候会因为浏览器缓存、响应头解析等问题出问题,我们可以先把后端返回的PDF转成Blob,再创建临时的Blob URL,这样渲染更可靠。

React组件示例:

import { useState, useEffect } from 'react';

function PdfViewer() {
  const [pdfUrl, setPdfUrl] = useState(null);

  useEffect(() => {
    const fetchAndPreparePdf = async () => {
      try {
        const response = await fetch('http://localhost:5000/fetch-pdf-content');
        if (!response.ok) throw new Error('加载PDF失败');
        // 把响应转成Blob对象
        const pdfBlob = await response.blob();
        // 创建临时的Blob URL
        const tempUrl = URL.createObjectURL(pdfBlob);
        setPdfUrl(tempUrl);

        // 组件卸载时清理URL,避免内存泄漏
        return () => URL.revokeObjectURL(tempUrl);
      } catch (err) {
        console.error('PDF加载出错:', err);
      }
    };

    fetchAndPreparePdf();
  }, []);

  if (!pdfUrl) {
    return <div>正在加载PDF...</div>;
  }

  return (
    <div style={{ width: '100%', height: '80vh' }}>
      {/* 用object标签,也可以替换成iframe,兼容性更好 */}
      <object
        data={pdfUrl}
        type="application/pdf"
        style={{ width: '100%', height: '100%' }}
      >
        <p>无法直接预览PDF,你可以<a href={pdfUrl} download="document.pdf">点击下载</a>查看。</p>
      </object>
    </div>
  );
}

export default PdfViewer;

方案二:用react-pdf库(功能更强大)

如果需要分页、缩放、搜索这些进阶功能,推荐用react-pdf库,它对PDF的渲染控制更灵活。

首先安装依赖:

npm install react-pdf

然后写组件:

import { useState, useEffect } from 'react';
import { Document, Page } from 'react-pdf';
// 别忘了引入样式,否则文本层和注释层会显示异常
import 'react-pdf/dist/esm/Page/AnnotationLayer.css';
import 'react-pdf/dist/esm/Page/TextLayer.css';

function AdvancedPdfViewer() {
  const [pdfUrl, setPdfUrl] = useState(null);
  const [totalPages, setTotalPages] = useState(null);
  const [currentPage, setCurrentPage] = useState(1);

  useEffect(() => {
    const fetchPdf = async () => {
      try {
        const response = await fetch('http://localhost:5000/fetch-pdf-content');
        if (!response.ok) throw new Error('获取PDF失败');
        const blob = await response.blob();
        setPdfUrl(URL.createObjectURL(blob));

        return () => URL.revokeObjectURL(blob);
      } catch (err) {
        console.error(err);
      }
    };

    fetchPdf();
  }, []);

  const handleDocumentLoad = ({ numPages }) => {
    setTotalPages(numPages);
  };

  if (!pdfUrl) {
    return <div>加载中...</div>;
  }

  return (
    <div style={{ width: '100%', padding: '20px' }}>
      <Document file={pdfUrl} onLoadSuccess={handleDocumentLoad}>
        <Page pageNumber={currentPage} />
      </Document>
      <div style={{ marginTop: '10px' }}>
        <p>第 {currentPage} 页 / 共 {totalPages} 页</p>
        <button
          disabled={currentPage <= 1}
          onClick={() => setCurrentPage(prev => prev - 1)}
          style={{ marginRight: '10px' }}
        >
          上一页
        </button>
        <button
          disabled={currentPage >= totalPages}
          onClick={() => setCurrentPage(prev => prev + 1)}
        >
          下一页
        </button>
      </div>
    </div>
  );
}

export default AdvancedPdfViewer;

为什么之前的object标签不行?

主要有两个原因:

  1. 后端返回的PDF数据因为没设置responseType被损坏了,浏览器无法解析
  2. 直接使用后端URL时,部分浏览器对响应头的处理有差异,导致无法正确渲染PDF内容

按照上面的步骤修改后,应该就能正常显示PDF啦!

备注:内容来源于stack exchange,提问作者Hitendra singh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.23 12:17:37