react-pdf 动态渲染导出PDF时UTF8字体失效 预览正常问题求助
问题根因
你遇到的是@react-pdf/renderer字体异步加载时序问题:
Font.register注册远程字体是异步加载逻辑,PDFViewer渲染在浏览器DOM树中,会自动等待字体加载完成后再渲染内容,因此预览显示正常PDFDownloadLink触发下载时会直接触发离线渲染生成PDF blob,若此时字体还未完全加载完成,会自动降级到系统默认字体,默认字体无UTF-8非英文字符集,就会出现乱码/方块字符- 额外可能原因:你使用的Roboto CDN字体是裁剪版本,未覆盖波兰语等东欧特殊字符集
解决方案
1. 监听字体加载状态,字体就绪后再开放下载入口
使用Font.loadAsync异步加载字体,加载完成后再渲染PDFDownloadLink组件,避免用户在字体未就绪时触发下载:
import { Font, PDFViewer, PDFDownloadLink } from '@react-pdf/renderer'; import { useState, useEffect } from 'react'; // 组件内逻辑 const [fontLoaded, setFontLoaded] = useState(false); useEffect(() => { const initFont = async () => { try { await Font.loadAsync({ family: "Roboto", src: "https://cdnjs.cloudflare.com/ajax/libs/ink/3.1.10/fonts/Roboto/roboto-light-webfont.ttf" }); setFontLoaded(true); } catch (err) { console.error("字体加载失败", err); } }; initFont(); }, []); // 渲染逻辑 return ( <> <PDFViewer> <MyDocument data={data} /> </PDFViewer> {/* 字体加载完成后才显示下载按钮 */} {fontLoaded ? ( <PDFDownloadLink document={<MyDocument data={data}/>} fileName="lista_składników.pdf"> {({ loading, error }) => { if (loading) return '正在生成文档...'; if (error) return '生成失败,请重试'; return '下载PDF'; }} </PDFDownloadLink> ) : ( <button disabled>字体加载中,暂时无法下载</button> )} </> )
2. 优先使用本地字体文件
将字体ttf文件下载到项目本地静态资源目录(比如public/fonts),避免CDN跨域、网络波动导致的字体加载失败问题,注册方式调整为:
Font.register({ family: "Roboto", src: process.env.PUBLIC_URL + "/fonts/roboto-light-webfont.ttf" });
3. 替换为全字符集字体
如果确认是当前Roboto字体字符集不全导致的乱码,可以替换为支持全球多语言的开源字体,比如Google的Noto Sans系列,完整覆盖东欧、中文等所有UTF-8字符。
4. 显式指定所有文本的字体属性
如果层级继承失效,可以给所有Text组件显式添加style={{fontFamily: "Roboto"}}属性,避免样式继承丢失。
效果参考
- 预览正常效果:

- 导出乱码原效果:

内容的提问来源于stack exchange,提问作者non
相关产品推荐
相关产品推荐

