Dompdf正确显示中文:UTF-8与中文字体配置

作者:技术拾光

时间:2026-05-28

浏览:357

dompdf 默认不支持中文,需手动配置支持 unicode 的中文字体(如 notosanscjk)、启用字体目录、设置默认字体并确保 html 编码统一为 utf-8,才能正常渲染中文文本。 如果你在使用 Dompdf(特别是 v0.8.0 及以上版本)将包含中文的 HTML 页面转换为 PDF

文章目录

Dompdf正确显示中文:UTF-8与中文字体配置

dompdf 默认不支持中文,需手动配置支持 unicode 的中文字体(如 notosanscjk)、启用字体目录、设置默认字体并确保 html 编码统一为 utf-8,才能正常渲染中文文本。

如果你在使用 Dompdf(特别是 v0.8.0 及以上版本)将包含中文的 HTML 页面转换为 PDF 时,遇到了满屏的“方块”或“□”符号,不必担心,这几乎是每位开发者都会遇到的问题。问题根源非常明确:字体缺失。Dompdf 自带的字体库(例如 DejaVu Sans)虽然支持大量 Unicode 字符,但不包含中日韩(CJK)汉字。因此,即使你的 HTML 在浏览器中显示正常,到了 PDF 渲染阶段,它也只能用“方块”来表示无法识别的汉字。

解决这个问题,本质上是一个标准的“四步走”流程。只要每一步都执行到位,中文显示问题便能迎刃而解。

正确解决方案(四步到位)

  1. 第一步:准备好中文字体文件
    你需要一个支持 CJK 的 TrueType 字体文件。推荐使用 Google 开源的 Noto Sans CJK 系列,例如“NotoSansCJKtc-Regular.ttf”(此为繁体中文版本,简体版本同理)。下载后,将其放置到项目目录中,例如 assets/fonts/。需要注意:字体文件名最好与后续代码中引用的名称保持一致(区分大小写,避免空格),这能减少许多不必要的麻烦。

  2. 第二步:在 PHP 代码中正确配置字体路径和默认字体
    这是最关键的一步。你必须通过 $options->set('fontDir', ...) 明确告知 Dompdf 字体文件的存放位置。同时,使用 $options->set('defaultFont', ...) 设置默认字体。注意,此处填写的是字体的注册名,而非文件名。Dompdf 在首次运行时,会解析 .ttf 文件并生成对应的缓存文件(.ufm 和 .php),因此首次渲染速度会稍慢,并且需要确保指定的 fontDir 目录具有写入权限。

  3. 第三步:清理 HTML/CSS 中无效的字体声明(这一步容易被忽略)
    在 HTML 的 标签中编写 @font-face 规则尝试引入本地或远程字体,在 Dompdf v0.8.0 中基本无效。它不支持动态加载此类字体。最稳妥的做法是:直接移除 HTML 模板中所有关于 @font-face 的 CSS 代码,完全依赖上一步在 PHP 层配置的 defaultFont。

  4. 第四步:确保整个流程的编码一致性

    • 在 HTML 模板的 中,必须包含 ;
    • 在 PHP 端,部分老教程建议使用 mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8') 进行编码转换。但对于现代框架(如 CodeIgniter 3+),只要确保 $html 字符串本身为 UTF-8 编码,直接使用即可,更为简洁。
    • 另外,无需再手动调用 define("DOMPDF_UNICODE_ENABLED", true),因为 v0.8.0+ 版本默认已启用了 Unicode 支持。

完整可运行代码示例

将上述步骤整合后,一个完整可用的代码示例如下:

require 'assets/dompdf1/autoload.inc.php';

//  关键:指定字体目录(使用绝对路径,并确保目录可读写)
define('DOMPDF_FONT_DIR', __DIR__ . '/assets/fonts/');

$options = new Options();
$options->set('isPhpEnabled', false); // 生产环境建议关闭 PHP 内联代码解析,更安全
$options->set('fontDir', DOMPDF_FONT_DIR);
$options->set('defaultFont', 'NotoSansCJKtc-Regular'); // 注意:此处为字体注册名,非文件名

$dompdf = new Dompdf($options);

// 假设你在 CodeIgniter 框架中获取视图内容
$html = $this->load->view('view_view', $data, TRUE);

// 只要 $html 本身是 UTF-8 编码,就无需额外转换。显式声明编码更稳妥。
$dompdf->loadHtml($html, 'UTF-8');
$dompdf->setPaper('A4', 'landscape');
$dompdf->render();
$dompdf->stream('View.pdf', ['Attachment' => false]);
exit;

常见陷阱与验证步骤

配置过程中,有几个常见“陷阱”需要特别注意:

  • 字体注册名 ≠ 文件名:字体文件“NotoSansCJKtc-Regular.ttf”在 Dompdf 内部的注册名通常为“NotoSansCJKtc-Regular”。如果不确定,可前往 dompdf/lib/fonts/ 目录,查看 Dompdf 自动生成的 .php 缓存文件来确认准确的注册名。
  • 字体目录权限:如果首次运行后,在 DOMPDF_FONT_DIR 目录下未看到新生成的 .ufm 或 .php 缓存文件,应首先检查该目录是否对 Web 服务器进程具有写入权限。
  • 避免混合字体声明:不要在 CSS 中编写类似 font-family: 'NotoSansCJK', DejaVu Sans; 的规则。Dompdf 在渲染 PDF 时,基本只认 PHP 中设置的 defaultFont,其他字体家族声明会被忽略。
  • 调试技巧:开启 error_reporting(E_ALL),观察是否有“Unable to load font”等错误抛出。同时,检查 DOMPDF_FONT_DIR 目录下是否成功生成了类似 notosanscjktc-regular.ufm 的文件,这是判断字体是否被成功加载和缓存的最直接证据。

完成以上配置后,Dompdf 便能清晰无误地渲染中文,方块乱码问题将彻底解决。从根本上讲,Dompdf 对中文字体的支持是一种“预加载加缓存映射”的机制,而非实时解析网络字体,因此这是一次配置、长期受益的工作。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章