Кодировка символов dompdf UTF-8

Я пытаюсь создать pdf с правильными символами, но есть "?" символы. Я создал тестовый файл php, где я пытаюсь найти лучшее решение. Если я открою в браузере html, я выгляжу нормально

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. Основная проблема заключается в том, что вы не указываете шрифт, который поддерживает ваши символы. Похоже, вы прочитали руководство, потому что вы используете пример шрифта из этого документа. Однако пример не предназначался для глобального применения к какому-либо документу, dompdf по умолчанию не включает firefly (китайский иероглифический шрифт) или Verdana.

Если вы не укажете шрифт, dompdf вернется к одному из основных шрифтов (Helvetica, Times Roman, Courier), которые поддерживают только кодировку Windows ANSI. Поэтому всегда устанавливайте для текста шрифт, который поддерживает кодировку 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
Какая версия домпдф? Шрифты 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: 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); определить (DOMPDF_ENABLE_HTML5PARSER, правда); в файле 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.

Вместо этого вы можете воспользоваться преимуществами диапазонов сценариев юникода регулярных выражений: 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