dompdf кодиране на знаци UTF-8

Опитвам се да създам pdf с правилни знаци, но има "?" знаци. Създадох тестов php файл, където се опитвам да намеря най-доброто решение. Ако отворя в браузъра, html I изглежда добре

UTF-8 --> UTF-8 : X Ponuka číslo € černý Češký 

Но когато погледна в pdf, виждам това

UTF-8 --> UTF-8 : X Ponuka ?íslo € ?erný ?ešký 

Ето целия ми код:

<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title>č s š Š</title>
</head>
<body>
<?php 

require_once("dompdf/dompdf_config.inc.php");
$tab = array("UTF-8", "ASCII", "Windows-1250", "ISO-8859-2", "ISO-8859-1", "ISO-8859-6", "CP1256"); 
$chain = '<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <style></style><title>č s š Š</title></head><body>';
foreach ($tab as $i) 
    { 
        foreach ($tab as $j) 
        { 
            $chain .= "<br> $i --> $j : ".iconv($i, $j, 'X Ponuka číslo € černý Češký <br>'); 
        } 
    } 
$chain .= '<p style="font-family: firefly, verdana, sans-serif;">??????X Ponuka číslo € černý Češký <br></p></body></html>';
echo $chain; 
echo 'X Ponuka číslo € černý Češký <br>'; 

$filename = 'pdf/_1.pdf';
$dompdf = new DOMPDF();
$dompdf->load_html($chain, 'UTF-8');
$dompdf->set_paper('a4', 'portrait'); // change these if you need to
$dompdf->render();
file_put_contents($filename, $dompdf->output());

?> 
</body>
</html>

Какво правя грешно? Опитах много много опции, които намерих :( Някаква идея?


person lostika    schedule 05.05.2013    source източник
comment
Повечето библиотеки не ви позволяват да зареждате данни в кодиране, различно от това, което изрично сте указали на библиотеката да зареди. Това често води до въпросителни знаци. Така че всъщност се чудя защо наистина мислите, че с DOMPDF това трябва да е различно? Също така просто да опитате през всички опции може да е добре за игра, но ако тази игра не даде бързи резултати, трябва да намерите различна стратегия, за да разберете какво се случва.   -  person hakre    schedule 05.05.2013
comment
Направих няколко опции, защото беше трудно да разбера как работи, наборът от знаци ISO-8859-2 няма никаква използваема информация за него, гугълнах много и исках UTF-8, където всеки знак е ок!   -  person lostika    schedule 05.05.2013
comment
Да, UTF-8 е добър избор, ако искате да поддържате всички (на компютърни системи) известни знаци. Във вашия код по-горе обаче правите множество кодирания в един и същи низ. Това никога не може да се получи добре. Вместо това е по-добре да разберете кое кодиране имат първоначално вашите низове. И след това със специфичното кодиране конвертирайте в UTF-8. Тук трябва да направите само едно повторно кодиране. Този отговор може да е интересен и за вас: stackoverflow.com/a/5159071/367456   -  person hakre    schedule 05.05.2013


Отговори (11)


Трябва да прочетете отново Unicode How to. Основният проблем е, че не сте посочили шрифт, който поддържа вашите знаци. Изглежда, че сте прочели инструкциите, защото използвате примерния шрифт от този документ. Въпреки това примерът не е предназначен да се прилага глобално към който и да е документ, dompdf не включва светулка (шрифт с китайски символи) или Verdana по подразбиране.

Ако не посочите шрифт, dompdf се връща към един от основните шрифтове (Helvetica, Times Roman, Courier), които поддържат само ANSI кодиране на Windows. Така че винаги се уверете, че стилизирате текста си с шрифт, който поддържа Unicode кодиране и има знаците, които трябва да показвате.

С dompdf 0.6.0 можете да използвате включените Deja Vu шрифтове. Така че следното трябва да работи (само HTML):

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<style>
  body { font-family: DejaVu Sans, sans-serif; }
</style>
<title>č s š Š</title>
</head>
<body>
  <p>??????X Ponuka číslo € černý Češký <br></p>
</body>
</html>
person BrianS    schedule 06.05.2013
comment
Каква версия на dompdf? Шрифтовете DejaVu бяха включени само от 0.6.x. Освен това множество неща могат да повлияят на изхода. Например вашият документ всъщност трябва да бъде кодиран като UTF-8, както и да посочите това кодиране в заглавката. - person BrianS; 20.11.2014
comment
версията беше 0.6.1 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>и шрифтът беше зададен с css и body tag: font-family: Helvetica,"Times New Roman", serif; - person andreas-supersmart; 21.11.2014
comment
@andreas-manusm ще трябва да използвате шрифтовете DejaVu, ако използвате знака директно. Вградените шрифтове трябва да могат да показват знака, ако го кодирате като &#0128; (позицията на знака на Windows ANSI). - person BrianS; 25.11.2014
comment
Междувременно поправих това, като написах евро, преди използвах „€“. - person andreas-supersmart; 27.11.2014
comment
Благодаря, че ме насочихте да използвам шрифтовете DejaVu - този път имах точен шаблон за попълване. Най-добрата практика за следващия проект е създаването на шаблон/дизайн, базиран на шрифт DejaVu. - person andreas-supersmart; 27.11.2014
comment
Това работи добре в последния dompdf (v0.7.0-beta2), изтеглен от github.com/dompdf/dompdf/ тагове. - person Xdg; 15.10.2015
comment
Търсих 3 дни за решение, преди да намеря това и сега работи перфектно. МНОГО БЛАГОДАРЯ !!! - person era-net; 15.09.2019
comment
@BrianS Как мога да добавя свой собствен шрифт? - person Alireza A2F; 28.01.2020

Имам UTF-8 символи, работещи с тази комбинация. Преди да предадете html към DOMpdf, направете скрито кодиране с това:

$html = mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8');

Използвайте шрифт DejaVu във вашия css

*{ font-family: DejaVu Sans; font-size: 12px;}

Уверете се, че сте задали utf-8 кодиране в HTML <head> тага

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

Сега всички специални знаци работят "ľ š č ť ž ý á í é"

person Frantisek    schedule 02.02.2015
comment
За мен посочването на <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> работи - person Raphioly-San; 12.01.2017

Само добавяне

  <style>
    *{ font-family: DejaVu Sans !important;}
  </style>

преди </head> Работи за мен.

person Prasant Kumar    schedule 17.01.2017
comment
Също така SET def(DOMPDF_ENABLE_HTML5PARSER, false); to def(DOMPDF_ENABLE_HTML5PARSER, true); във файла dompdf_config.inc.php. - person Prasant Kumar; 21.02.2018

utf8_decode() свърши работа за мен с някои немски преводи като ä и ü.

echo utf8_decode('X Ponuka číslo € černý Češký <br>');
person Dirk de Boer    schedule 16.04.2018

Dompdf не поддържа резервни шрифтове, така че не можете да използвате любимия си шрифт, ако не поддържа вашите знаци, и също така не можете да зададете друг шрифт да бъде резервен шрифт за тези знаци като droid sans fallback.

Това, което можете да направите вместо това, е да се възползвате от диапазоните на уникод скриптове на regex: https://www.regular-expressions.info/unicode.html, за да обвиете тези блокове текст в участъци и да им дадете резервния шрифт.

Пример:

$body = 'test 简化字 彝語/彝语 test číslo € černý Češký';

$cjk_scripts = 'Bopomofo|Han|Hiragana|Katakana';
$cjk_scripts = preg_replace('/[a-zA-Z_]+/', '\\p{$0}', $cjk_scripts);

// wrap the CJK characters into a span with it's own font
$body = preg_replace("/($cjk_scripts)+/isu", '<span class="cjk">$0</span>', $body);

// a font that supports CJK characters
$cjk_font_path = APP_PATH.'/fonts/DroidSansFallbackFull.ttf';

$html = <<<HTML
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<style type="text/css">
@font-face {
    font-family: 'DroidSansFallbackFull';
    font-style: normal;
    font-weight: 400;
    src: url('$cjk_font_path') format('truetype');
}
body {
    font-family: DejaVu Sans, sans-serif;;
}
.cjk {
    font-family: DroidSansFallbackFull, sans-serif;
}
</style>
</head>
<body>$body</body>
</html>
HTML;

$dompdf = new \DOMPDF();
$dompdf->set_paper('A4');
$dompdf->load_html($html);
$dompdf->render();

$dompdf->stream('test.pdf', ['Attachment'=>0]);

Свързани: https://github.com/dompdf/dompdf/issues/1508

person Timo Huovinen    schedule 27.12.2018

Нищо от споменатите отговори не ми помогна. След часове на борба преминах към niklasravnsborg/laravel-pdf има почти същия синтаксис и употреба , и всичко работи както трябва.

person Fusion    schedule 02.03.2017

Ако нямате нищо против да имате само един набор от знаци, можете да промените всеки набор от знаци в dompdf_font_family_cache.dist.php

точно като

<?php
$distFontDir = $rootDir . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . 'fonts' . DIRECTORY_SEPARATOR;
return array(
    'sans-serif' =>
    array(
        'bold' => $distFontDir . 'DejaVuSans-Bold',
        'bold_italic' => $distFontDir . 'DejaVuSans-BoldOblique',
        'italic' => $distFontDir . 'DejaVuSans-Oblique',
        'normal' => $distFontDir . 'DejaVuSans'
    ),
    'times' =>
    array(
        'bold' => $distFontDir . 'DejaVuSans-Bold',
        'bold_italic' => $distFontDir . 'DejaVuSans-BoldOblique',
        'italic' => $distFontDir . 'DejaVuSans-Oblique',
        'normal' => $distFontDir . 'DejaVuSans'
    ),
    'times-roman' =>
    array(
        'bold' => $distFontDir . 'DejaVuSans-Bold',
        'bold_italic' => $distFontDir . 'DejaVuSans-BoldOblique',
        'italic' => $distFontDir . 'DejaVuSans-Oblique',
        'normal' => $distFontDir . 'DejaVuSans'
    ),
    'courier' =>
    array(
        'bold' => $distFontDir . 'DejaVuSans-Bold',
        'bold_italic' => $distFontDir . 'DejaVuSans-BoldOblique',
        'italic' => $distFontDir . 'DejaVuSans-Oblique',
        'normal' => $distFontDir . 'DejaVuSans'
    ),
    'helvetica' =>
    array(
        'bold' => $distFontDir . 'DejaVuSans-Bold',
        'bold_italic' => $distFontDir . 'DejaVuSans-BoldOblique',
        'italic' => $distFontDir . 'DejaVuSans-Oblique',
        'normal' => $distFontDir . 'DejaVuSans'
    ),
    'zapfdingbats' =>
    array(
        'bold' => $distFontDir . 'DejaVuSans-Bold',
        'bold_italic' => $distFontDir . 'DejaVuSans-BoldOblique',
        'italic' => $distFontDir . 'DejaVuSans-Oblique',
        'normal' => $distFontDir . 'DejaVuSans'
    ),
    'symbol' =>
    array(
        'bold' => $distFontDir . 'DejaVuSans-Bold',
        'bold_italic' => $distFontDir . 'DejaVuSans-BoldOblique',
        'italic' => $distFontDir . 'DejaVuSans-Oblique',
        'normal' => $distFontDir . 'DejaVuSans'
    ),
    'serif' =>
    array(
        'bold' => $distFontDir . 'DejaVuSans-Bold',
        'bold_italic' => $distFontDir . 'DejaVuSans-BoldOblique',
        'italic' => $distFontDir . 'DejaVuSans-Oblique',
        'normal' => $distFontDir . 'DejaVuSans'
    ),
    'monospace' =>
    array(
        'bold' => $distFontDir . 'DejaVuSans-Bold',
        'bold_italic' => $distFontDir . 'DejaVuSans-BoldOblique',
        'italic' => $distFontDir . 'DejaVuSans-Oblique',
        'normal' => $distFontDir . 'DejaVuSans'
    ),
    'fixed' =>
    array(
        'bold' => $distFontDir . 'DejaVuSans-Bold',
        'bold_italic' => $distFontDir . 'DejaVuSans-BoldOblique',
        'italic' => $distFontDir . 'DejaVuSans-Oblique',
        'normal' => $distFontDir . 'DejaVuSans'
    ),
    'dejavu sans' =>
    array(
        'bold' => $distFontDir . 'DejaVuSans-Bold',
        'bold_italic' => $distFontDir . 'DejaVuSans-BoldOblique',
        'italic' => $distFontDir . 'DejaVuSans-Oblique',
        'normal' => $distFontDir . 'DejaVuSans'
    ),
    'dejavu sans mono' =>
    array(
        'bold' => $distFontDir . 'DejaVuSansMono-Bold',
        'bold_italic' => $distFontDir . 'DejaVuSansMono-BoldOblique',
        'italic' => $distFontDir . 'DejaVuSansMono-Oblique',
        'normal' => $distFontDir . 'DejaVuSansMono'
    ),
    'dejavu serif' =>
    array(
        'bold' => $distFontDir . 'DejaVuSerif-Bold',
        'bold_italic' => $distFontDir . 'DejaVuSerif-BoldItalic',
        'italic' => $distFontDir . 'DejaVuSerif-Italic',
        'normal' => $distFontDir . 'DejaVuSerif'
    )
)
?>

Знам, че не е най-добрият начин, но спестява много време

person David Škarda    schedule 19.03.2017
comment
Това беше моят проблем, не съм задал правилно $rootDir! Шрифтовете не бяха прочетени. - person Jan Matousek; 02.01.2020

Имах подобен проблем и в крайна сметка използвах tcpdf. Надявам се това да е полезно. http://www.tcpdf.org/
Проблемът беше шрифтът, който използвах. Успях за да получите правилния изход, използвайки този шрифт 'freeserif'. Предполагам, че може да е възможно да получите същия изход, използвайки този шрифт с dompdf.

$pdf->SetFont('freeserif', '', 12);

Ето мостра, която използвах. tcpdf utf-8 пример

<?php
header('Content-type: text/html; charset=UTF-8') ;//chrome
require_once('tcpdf_include.php');

// create new PDF document
$pdf = new TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);

$pdf->setFontSubsetting(true);

$pdf->SetFont('freeserif', '', 12);

$pdf->AddPage();

$utf8text = '
<html><head>  
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /></head><body>
<b>Ponuka číslo € černý Češký </b></br>
සිංහල  </br>
<u>தேமல </u> </br>
</body></html>';

$pdf->SetTextColor(0, 63, 127);

$pdf->writeHTML($utf8text, true, 0, true, true);

$pdf->Output('example_008.pdf', 'I');

?>
person Deshan    schedule 11.09.2013

Китайските йероглифи понякога създават проблеми. Важната част е да имате добър шрифт ето списък, който можете да изтеглите.

Избрах първо име "Kai Bold Font" тук е страница за изтегляне

След това го поставете на вашата хостинг услуга в публична папка. Сложих го в

http://192.168.10.10/fonts/pdf/wts11.ttf

и ето моят html пример

$html = <<<EOT
<!DOCTYPE html>
<html>
<head>
   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
   <style>
    @font-face {
      font-family: chinese;
        src: url('http://192.168.10.10/fonts/pdf/wts11.ttf') format('truetype');
    }
    .chineseLanguage { font-family: chinese; }
      body {font-family: DejaVu Sans, sans-serif;}
   </style>
</head>
<body>
    Chinese
    <div class='chineseLanguage'>
        忠烈祠
        中文 - 这工作<br> 
    </div>
    hello world <br> 
    Russian - русский текст <br>
    Greek - α,β,γ,δ,ε <br>
    chars - !@#$%^&* -=- €   <br><br>
    <br>
    Hebrew (iw)<br><br>
    דג סקרן שט בים מאוכזב ולפתע מצא לו חברה איך הקליטה<br>
    <br>    
</body>
</html>
EOT;

PS. има малък шанс да имате нужда от този комплект:

ini_set("allow_url_fopen", true);
person Yevgeniy Afanasyev    schedule 27.04.2018

Имах същия проблем и го реших много просто. Просто импортирайте шрифтове на Google с необходимия езиков поднабор във вашия CSS файл, който се използва при генериране на HTML. Посочете utf-8 във вашия HTML файл и той работи...

@import url('https://fonts.googleapis.com/css?family=Roboto:400,700&subset=latin-ext');
body {font-family: 'Roboto', sans-serif;}
person general666    schedule 11.07.2018

Тук има много отговори, трудно успях да намеря такива, за да осигуря надеждна поддръжка на различни езици. Вярвам, че за тези от нас, които създават разпределен софтуер, има и блокове за настройка на сървъра, които спират някои функции като @import и src:url() в pdfdom, които автоматично работят за вграждане на шрифт.

Следното решение работи в много сървъри и локално хоствани сайтове и не изисква достъп до командния ред:

  1. Извлечете шрифта, който искате да използвате като .ttf (за езикова поддръжка, включително кирилица, гръцки, деванагари, латиница и виетнамски, използвахме Noto Sans с отметка на всички незадължителни езици)
  2. Изпълнете/вградете следния скрипт и задействайте PDFBuilder_install_font_family() само ВЕДНЪЖ (единично инсталиране)

Същност за PDFBuilder_install_font_family(): https://gist.github.com/woodyhayday/f8dc36cc7ec922bc1894f33eb2b0e928

person Woody Hayday    schedule 16.01.2020