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

React多语言PDF渲染下载问题:寻求@react-pdf/renderer替代方案

解决@react-pdf/renderer多语言PDF显示 tofu 字符的方案

先修正你的字体配置错误

你当前把所有语言的Noto字体都注册到同一个family且相同fontWeight下,@react-pdf没法自动匹配对应语言的字体文件,这才导致了tofu(方块)字符。正确的做法是给每个语言的字体单独注册家族,或者直接给不同语言的文本指定对应字体。

修正后的注册代码

import NotoSansMedium from '../assets/fonts/noto/NotoSans-Medium.ttf';
import NotoSansArabic from '../assets/fonts/noto/NotoSansArabic-Medium.ttf';
import NotoSansHebrew from '../assets/fonts/noto/NotoSansHebrew-Medium.ttf';
import NotoSansJP from '../assets/fonts/noto/NotoSansJP-Medium.ttf';
import NotoSansKR from '../assets/fonts/noto/NotoSansKR-Medium.ttf';
import NotoSansSC from '../assets/fonts/noto/NotoSansSC-Medium.ttf';
import NotoSansTC from '../assets/fonts/noto/NotoSansTC-Medium.ttf';

// 为每种语言单独注册字体家族
Font.register({
  family: 'NotoSans',
  src: NotoSansMedium,
  fontWeight: 'medium'
});

Font.register({
  family: 'NotoSansArabic',
  src: NotoSansArabic,
  fontWeight: 'medium'
});

Font.register({
  family: 'NotoSansHebrew',
  src: NotoSansHebrew,
  fontWeight: 'medium'
});

Font.register({
  family: 'NotoSansJP',
  src: NotoSansJP,
  fontWeight: 'medium'
});

Font.register({
  family: 'NotoSansKR',
  src: NotoSansKR,
  fontWeight: 'medium'
});

Font.register({
  family: 'NotoSansSC',
  src: NotoSansSC,
  fontWeight: 'medium'
});

Font.register({
  family: 'NotoSansTC',
  src: NotoSansTC,
  fontWeight: 'medium'
});

渲染时给对应语言的文本指定字体:

<Text fontFamily="NotoSans">English content</Text>
<Text fontFamily="NotoSansArabic">النص العربي</Text>
<Text fontFamily="NotoSansHebrew">טקסט עברי</Text>
<Text fontFamily="NotoSansSC">中文简体内容</Text>

替代方案

如果觉得手动指定字体太繁琐,试试下面这些工具:

1. pdf-lib

pdf-lib 对字体嵌入和文本布局支持更灵活,你可以给不同语言的文本块单独嵌入对应字体,也可以用包含全语言字符的Noto通用字体(注意文件体积会很大)。

示例代码:

import { PDFDocument, rgb } from 'pdf-lib';
import NotoSansSC from '../assets/fonts/noto/NotoSansSC-Medium.ttf';
import NotoSansArabic from '../assets/fonts/noto/NotoSansArabic-Medium.ttf';

async function createMultiLangPDF() {
  const pdfDoc = await PDFDocument.create();
  const page = pdfDoc.addPage([600, 800]);

  // 嵌入所需字体
  const chineseFont = await pdfDoc.embedFont(NotoSansSC);
  const arabicFont = await pdfDoc.embedFont(NotoSansArabic);

  // 添加中文文本
  page.drawText('中文简体内容', {
    x: 50,
    y: 700,
    font: chineseFont,
    size: 16,
    color: rgb(0, 0, 0),
  });

  // 添加阿拉伯文本(RTL布局需额外处理)
  page.drawText('النص العربي', {
    x: 50,
    y: 650,
    font: arabicFont,
    size: 16,
    color: rgb(0, 0, 0),
  });

  const pdfBytes = await pdfDoc.save();
  // 触发下载
  const blob = new Blob([pdfBytes], { type: 'application/pdf' });
  const link = document.createElement('a');
  link.href = URL.createObjectURL(blob);
  link.download = 'multi-lang.pdf';
  link.click();
}

2. jsPDF + html2canvas

如果你的内容是基于HTML的,先通过html2canvas把包含多语言的HTML转成图片,再用jsPDF生成PDF。只要浏览器能正常显示多语言,生成的PDF就没问题。

示例代码:

import jsPDF from 'jspdf';
import html2canvas from 'html2canvas';

async function generatePDF() {
  const targetElement = document.getElementById('multi-lang-content');
  const canvas = await html2canvas(targetElement);
  const imgData = canvas.toDataURL('image/png');

  const pdf = new jsPDF('p', 'mm', 'a4');
  const imgWidth = 210;
  const pageHeight = 297;
  const imgHeight = (canvas.height * imgWidth) / canvas.width;
  let remainingHeight = imgHeight;
  let yPosition = 0;

  pdf.addImage(imgData, 'PNG', 0, yPosition, imgWidth, imgHeight);
  remainingHeight -= pageHeight;

  // 处理长内容分页
  while (remainingHeight >= 0) {
    yPosition = remainingHeight - imgHeight;
    pdf.addPage();
    pdf.addImage(imgData, 'PNG', 0, yPosition, imgWidth, imgHeight);
    remainingHeight -= pageHeight;
  }

  pdf.save('multi-lang.pdf');
}

3. Puppeteer(服务器端生成)

如果前端方案有局限,用Puppeteer在Node.js端渲染HTML页面生成PDF。它依赖Chrome的渲染引擎,对多语言、复杂样式的支持是最好的。

示例代码(Node.js环境):

const puppeteer = require('puppeteer');

async function generatePDF() {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();

  // 加载目标HTML页面(本地文件或远程URL都可以)
  await page.goto('file:///path/to/your/multi-lang-page.html', { waitUntil: 'networkidle0' });

  // 生成PDF
  await page.pdf({
    path: 'multi-lang.pdf',
    format: 'A4',
    printBackground: true
  });

  await browser.close();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 17:26:05