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

如何在React中查看从Node.js后端传来的PDF Array Buffer?

React中查看后端加密传输的PDF文件

首先你需要在前端完成解密操作——因为后端用encryptionOfData加密了响应数据,前端必须用对应的decryptionOfData函数解密,才能拿到原始的PDF二进制数据。

步骤1:前端请求并解密数据

假设你用axios发送请求(用fetch逻辑类似),拿到加密响应后先解密:

import axios from 'axios';

// 前端实现与后端匹配的解密函数
const decryptionOfData = (encryptedData) => {
  // 这里写对应后端加密逻辑的解密代码,比如AES对称解密
  // 解密后返回原始PDF二进制数据(Uint8Array/ArrayBuffer类型)
};

const fetchAndPreviewPDF = async (username) => {
  try {
    // 必须指定响应类型为arraybuffer,防止二进制数据乱码
    const response = await axios.get(`/api/get-certificate?username=${username}`, {
      responseType: 'arraybuffer'
    });

    // 解密得到原始PDF数据
    const decryptedPDFData = decryptionOfData(response.data);

    // 进入预览处理环节
    handlePDFPreview(decryptedPDFData);
  } catch (error) {
    console.error('获取/解密PDF失败:', error);
  }
};

步骤2:将解密后的数据转为Blob

浏览器处理PDF需要Blob对象,先完成格式转换:

const handlePDFPreview = (pdfData) => {
  const pdfBlob = new Blob([pdfData], { type: 'application/pdf' });
  // 选择以下任意一种方式实现预览
};

方式1:用iframe快速预览

适合简单场景,直接在页面嵌入iframe展示:

const handlePDFPreview = (pdfData) => {
  const pdfBlob = new Blob([pdfData], { type: 'application/pdf' });
  const blobUrl = URL.createObjectURL(pdfBlob);

  // 动态创建iframe插入页面
  const iframe = document.createElement('iframe');
  iframe.src = blobUrl;
  iframe.width = '100%';
  iframe.height = '800px';
  document.getElementById('pdf-container').appendChild(iframe);

  // 页面卸载时释放Blob URL,避免内存泄漏
  window.addEventListener('beforeunload', () => {
    URL.revokeObjectURL(blobUrl);
  });
};

React组件内也可直接写JSX:

const PDFViewer = ({ pdfBlobUrl }) => {
  return (
    <div id="pdf-container">
      {pdfBlobUrl && <iframe src={pdfBlobUrl} width="100%" height="800px" title="PDF预览" />}
    </div>
  );
};

方式2:用PDF.js自定义渲染(支持分页/样式定制)

如果需要更灵活的控制(比如分页、自定义样式),可以用官方pdfjs-dist库:

  1. 先安装依赖:
npm install pdfjs-dist
  1. 组件示例:
import { useState, useEffect } from 'react';
import * as pdfjsLib from 'pdfjs-dist';
import 'pdfjs-dist/build/pdf.worker.entry';

// 设置PDF.js的worker路径
pdfjsLib.GlobalWorkerOptions.workerSrc = '//cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js';

const CustomPDFViewer = ({ pdfData }) => {
  const [pdfDoc, setPdfDoc] = useState(null);
  const [currentPage, setCurrentPage] = useState(1);

  useEffect(() => {
    const loadPDF = async () => {
      const pdfBlob = new Blob([pdfData], { type: 'application/pdf' });
      const pdfUrl = URL.createObjectURL(pdfBlob);
      const doc = await pdfjsLib.getDocument(pdfUrl).promise;
      setPdfDoc(doc);
      // 页面卸载时释放URL
      return () => URL.revokeObjectURL(pdfUrl);
    };
    if (pdfData) loadPDF();
  }, [pdfData]);

  const renderCurrentPage = async () => {
    if (!pdfDoc) return;
    const page = await pdfDoc.getPage(currentPage);
    const canvas = document.getElementById('pdf-canvas');
    const ctx = canvas.getContext('2d');
    const viewport = page.getViewport({ scale: 1.5 });

    canvas.height = viewport.height;
    canvas.width = viewport.width;
    await page.render({ canvasContext: ctx, viewport }).promise;
  };

  useEffect(() => {
    renderCurrentPage();
  }, [pdfDoc, currentPage]);

  return (
    <div>
      <canvas id="pdf-canvas" />
      <div style={{ marginTop: '16px' }}>
        <button onClick={() => setCurrentPage(p => Math.max(1, p - 1))} disabled={currentPage === 1}>
          上一页
        </button>
        <span style={{ margin: '0 16px' }}>第 {currentPage} / {pdfDoc?.numPages || 0} 页</span>
        <button onClick={() => setCurrentPage(p => Math.min(pdfDoc.numPages, p + 1))} disabled={currentPage === pdfDoc?.numPages}>
          下一页
        </button>
      </div>
    </div>
  );
};

方式3:生成临时链接供打开/下载

如果不需要页面内预览,可生成链接让用户在新标签页打开或下载:

const handlePDFPreview = (pdfData) => {
  const pdfBlob = new Blob([pdfData], { type: 'application/pdf' });
  const blobUrl = URL.createObjectURL(pdfBlob);

  // 方式A:在新标签页打开PDF
  window.open(blobUrl, '_blank');

  // 方式B:触发下载
  const downloadBtn = document.createElement('a');
  downloadBtn.href = blobUrl;
  downloadBtn.download = `${username}_certificate.pdf`;
  downloadBtn.click();

  // 延迟释放Blob URL
  setTimeout(() => URL.revokeObjectURL(blobUrl), 1000);
};

内容的提问来源于stack exchange,提问作者Manas S. Roy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 22:50:26