FPDF utf-8编码(如何操作)

98

有人知道如何在FPDF软件包中设置编码为UTF-8吗?或者至少设置为支持希腊字符的ISO-8859-7(希腊语)?

基本上我想创建一个包含希腊字符的PDF文件。

任何建议都会有所帮助。 George


如果您想使用更多的语言,您需要UTF8,因此您可以使用tFPDF。请查看composer package - robsch
20个回答

137
不要使用UTF-8编码。标准FPDF字体使用ISO-8859-1或Windows-1252编码。可以使用utf8_decode()进行转换为ISO-8859-1编码: $str = utf8_decode($str); 但一些字符例如欧元符号无法正确转换。如果iconv扩展可用,则应该采用以下方法: $str = iconv('UTF-8', 'windows-1252', $str);

28
我不认为这会有所帮助。你的回答解释了如何使用ISO-8859-1或windows-1252编码生成PDF,但这些编码对于非拉丁语言并不适用。更不用说输出多语言(多字母表)文本了。 - Томица Кораћ
5
@Rafiq:不要使用“旧的”FPDF,而是使用我在答案中发布的更新的UTF8版本tFPDF。 - Tarsis
1
注意:使用ISO-8859-1时,€字符将无法正常工作(该字符集中没有欧元符号),请改用ISO-8859-15。 - BurninLeo
1
@BurninLeo:ISO-8859-15 并没有更好,所有这些编码都有相同的字符限制,所以 -15 有 €,但缺少 ´ 或 ½。唯一真正的解决方案是使用 UTF-8 而不是避免它——正如我的答案所示。 - Tarsis
3
tFPDF支持Unicode,但它已经三年没有更新了,而FPDF最近有更新,这使得tFPDF已经过时了。在使用tFPDF时请记住这一点。 - Agilis
显示剩余6条评论

47

还有一种官方的UTF-8版本FPDF叫做tFPDF http://www.fpdf.org/en/script/script92.php

您可以轻松地从原始FPDF切换,只需确保您也使用一个Unicode字体,如上面链接中的示例或我的代码所示:

<?php

//this is a UTF-8 file, we won't need any encode/decode/iconv workarounds

//define the path to the .ttf files you want to use
define('FPDF_FONTPATH',"../fonts/");
require('tfpdf.php');

$pdf = new tFPDF();
$pdf->AddPage();

// Add Unicode fonts (.ttf files)
$fontName = 'Helvetica';
$pdf->AddFont($fontName,'','HelveticaNeue LightCond.ttf',true);
$pdf->AddFont($fontName,'B','HelveticaNeue MediumCond.ttf',true);

//now use the Unicode font in bold
$pdf->SetFont($fontName,'B',12);

//anything else is identical to the old FPDF, just use Write(),Cell(),MultiCell()... 
//without any encoding trouble
$pdf->Cell(100,20, "Some UTF-8 String");

//...
?>

我认为使用这种方法比在各处使用utf8_decode()更加优雅,而且在AddFont()中直接使用.ttf文件的能力也是一个优点。
在这里提出任何其他答案都只是避免或解决问题的一种方式,而避免使用UTF-8对于一个现代化的项目来说并不是一个真正的选择。
还有其他的选择,如mPDF或TCPDF(和其他),它们基于FPDF但提供了高级功能,支持UTF-8并可以解释HTML代码(当然有限,因为没有直接将HTML转换为PDF的方法)。 大部分FPDF代码可以直接用于这些库中,所以迁移代码非常容易。

https://github.com/mpdf/mpdf http://www.tcpdf.org/


1
没有任何iconv和decode解决方案适用于更特殊的字符(♠♥☺äκόσμος)。但是,如果您只是将fpdf.php替换为tpdf.php文件,一切都会开始正常工作,并且您的文件会变得更小,这是额外的好处。非常好的修复方法。 - Sebastian
1
FPDF和tFPDF是分开的分支吗?有人知道为什么在FPDF页面上tFPDF被隐藏得这么好吗?在切换之前有任何需要注意的缺点吗? - BurninLeo
1
我不确定为什么他们没有将其作为默认的FPDF版本,但它直接链接在主页http://www.fpdf.org/上,并且如在那里提到的,tFPDF的功能最初是为mPDF开发的。我已经在生产环境中使用了tFPDF来生成很多PDF文件,除了UTF-8和字体更改外,我认为它与原版完全相同。从未遇到任何问题。 - Tarsis
1
tFPDF是FPDF的脚本或扩展。由于FPDF最近已经更新,因此它被认为已过时(3年前更新)。tFPDF的作者没有维护它,与tFPDF相关的GitHub也没有更新。请参见:https://github.com/rev42/tfpdf - Agilis
只要你不需要更多的功能,我认为这没有问题。顺便说一下,最后一次(小)更新是在4个月前 - 还是比不支持UTF-8好。无论如何,我更喜欢TCPDF或mPDF,它们都基于FPDF但提供了高级功能,并支持HTML代码。 - Tarsis
显示剩余2条评论

42
这个问题有一个非常简单的解决方案。 在文件fpdf.php中找到以下代码行:
if($txt!=='')
{

这是我版本的fpdf中的第648行。 插入以下代码:

$txt = iconv('utf-8', 'cp1252', $txt);

(代码行之上)
if($align=='R')

这适用于所有德语特殊字符,应该也适用于希腊特殊字符。否则,请使用您需要的相应字符集替换cp1252。您可以在此处查看所有支持的字符:http://en.wikipedia.org/wiki/Windows-1252 我在此处看到了解决方案:http://fudforum.org/forum/index.php?t=msg&goto=167345 请使用我上面的示例代码,因为原作者忘记在utf和8之间添加破折号。
希望以上内容有所帮助。
Daan

很好,即使将FPDF更新到支持PHP7的版本以正确显示特殊字符,这仍然有效或需要。 - Aren
2
这个命令对我有效,$txt = iconv('utf-8', 'cp1252', $txt); 谢谢。 - Patrick Arguello
1
只是一个惊人的简单解决方案。可悲的是它被藏在 StackOverflow 的一个不起眼的地方 :) - Pieter-Jan Casteels
这改变了我的间距 - 现在有些行提前断开了。但至少它似乎可以工作 - 以前土耳其字母对我根本不起作用,现在至少我看到了一些东西。 - Cold_Class

10

你需要先生成一个字体。你必须使用FPDF包中包含的MakeFont实用程序。我在Linux上使用了一份稍微扩展过的演示脚本:

<?php
// Generation of font definition file for tutorial 7
require('../makefont/makefont.php');

$dir = opendir('/usr/share/fonts/truetype/ttf-dejavu/');
while (($relativeName = readdir($dir)) !== false) {
    if ($relativeName == '..' || $relativeName == '.')
        continue;
    MakeFont("/usr/share/fonts/truetype/ttf-dejavu/$relativeName",'ISO-8859-2');
}
?>

然后我将生成的文件复制到我的网站的font目录中,使用了这个:

$pdf->Cell(80,70, iconv('UTF-8', 'ISO-8859-2', 'Buňka jedna'),1);

(我正在处理一个表格。)这对我的语言有效(Buňka jedna是捷克语中的Cell one)。捷克语属于中欧语言,也是ISO-8859-2编码。遗憾的是,FPDF用户被迫失去了UTF-8编码的优势,您无法在PDF中获得以下内容:

Městečko Fruens Bøge

在 ISO-8859-2 中,丹麦字母 ø 变成了 ř

解决建议:你需要获取一种希腊字体,使用正确的编码 (ISO-8859-7) 生成该字体,并使用与字体相同的目标编码来使用 iconv


8
我该怎样在FPDF中创建支持中文、日文、俄文等的PDF文件呢?

(下面是使用代码的快照)

我想提供:问题的概述,解决方案,带有工作代码的Github项目以及具有预期结果的在线示例PDF。

问题:

  1. 如Tarsis所述,将FPDF更换为TFPDF。
  2. 您实际上需要一种支持您正在使用的UTF-8字符的字体。

    例如,仅使用Helvetica并尝试显示日语将不起作用。如果您使用Font Forge或其他字体工具,可以滚动到字体的中文字符并查看它们为空白。

    谷歌有一个字体(Noto font),其中包含所有语言,大小通常是文本大小的几倍。因此,您可以看到为什么许多字体简单地无法涵盖每种语言。

解决方案:

我正在使用开源的rounded-mgenplus-20140828.ttf和ZCOOL_QingKe_HuangYou.ttf字体包来处理日文和中文,这些字体包在许多开源项目中都可以找到。 在tFPDF本身中,或者像class HTMLtoPDF extends tFPDF {...}这样的新继承类中,您需要进行以下操作...
$this->AddFont('japanese', '', 'rounded-mgenplus-20140828.ttf', true);
$this->SetFont('japanese', '', 14);
$this->Write(14, '日本語');

应该没有更多的内容了!

GitHub 上的代码包:

https://github.com/HoldOffHunger/php-html-to-pdf

工作中,日语在线演示:

https://www.earthfluent.com/privacy.pdf?language=ja


5

只需编辑fpdf.php文件中的函数单元格,查找看起来像这样的行

function cell ($w, $h = 0, $txt = '', $border = 0, $ln = 0, $align = '', $fill = false, $link = '')
{ 

在找到这行代码之后,在 { 后面添加内容。
$txt = utf8_decode($txt);

保存文件后,准备就绪,重音符号和UTF8编码将正常工作 :)


5

这个答案对我无效,我还需要对字符串进行HTML解码。请参考

iconv('UTF-8', 'windows-1252', html_entity_decode($str));

感谢来自StackOverflow的emfi提供帮助,解决了在使用tFPDF扩展中的html_entity_decode问题。


4

4
链接似乎已失效。 - robsch

4
我想回答一下那些因为框架集成等原因而没有转换到TFPDF的人。
请前往:http://www.fpdf.org/makefont/index.php 使用与您要使用的语言兼容的.ttf字体。确保选择正确的编码数字以适合您的语言。下载文件并将它们粘贴到当前的FPDF字体目录中。
使用以下内容来激活新字体: $pdf->AddFont($font_name,'','Your_Font_Here.php'); 然后您可以正常地使用$pdf->SetFont
对于字体本身,请使用iconv进行转换为UTF-8。例如,如果您使用希伯来语,则可以执行iconv('UTF-8', 'windows-1255', $first_name)
将Windows编码数字替换为您的语言编码。
对于从右到左的语言,一个快速的解决方法是执行strrev(iconv('UTF-8', 'windows-1255', $first_name))

4

您可以创建一个继承FPDF的类,并添加以下内容:

class utfFPDF extends FPDF {

function Cell($w, $h=0, $txt="", $border=0, $ln=0, $align='', $fill=false, $link='')
{
    if (!empty($txt)){
        if (mb_detect_encoding($txt, 'UTF-8', false)){
            $txt = iconv('UTF-8', 'ISO-8859-5', $txt);

        }
    }
    parent::Cell($w, $h, $txt, $border, $ln, $align, $fill, $link);

} 

}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接