PHP. Создание PDF-файлов «на лету» в кодировке UTF-8

Как-то решал я задачу по созданию скрипта на PHP для генерации PDF-файлов. Важное условие – входящие данные в кодировке UTF-8.

Казалось бы, какие могут быть сложности, ведь PHP-шных классов для генерации PDF написано достаточно, но оказалось что решение этой задачи целая проблема.

На лабораторный стол ко мне попали следующие классы: FPDF, TCPDF, mPDF, UFPDF.

Исследование показало, что:

  • класс FPDF не дружит с юникодом;
  • TCPDF и mPDF не работали из-за лимитов памяти для выполнения на хостинге (бывает и такое);
  • класс UFPDF (на самом деле это модифицированная версия FPDF, которая работает с UTF-8) на первый взгляд показался мне подходящим кандидатом. Его я и стал использовать.

Походу использования класса, обнаружилось несколько проблем. Сначала были проблемы с украинскими символами, которые решились парочкой правок в коде UFPDF. Но потом, когда я начал рисовать таблицы, выяснилось что класс не умеет нормально переносить текст в ячейках таблицы. После вызова метода MultiCell текст в следущей ячейке сползал вниз.

Пришлось маленько «поломать» голову. В результате получился класс UFPDF2, который является расширением UFPDF и в котором корректно работает метод MultiCell.

UFPDF2 работает аналогично UFPDF, который, с свою очередь, работает также как и FPDF. Поэтому пользуемся документацией FPDF.

Пример использования класса:

define('FPDF_FONTPATH', 'font/');
include_once('ufpdf2.php');

$pdf = new UFPDF2();
$pdf->Open();
$pdf->SetTitle("Тестовый документ");
$pdf->SetAuthor('Steven Wittens');
$pdf->AddFont('LucidaSansUnicode', '', 'lsansuni.php');
$pdf->AddPage();
$pdf->SetFont('LucidaSansUnicode', '', 32);
$pdf->Write(12, "Test.\n");
$pdf->Write(12, "Тестовая строка.\n");
$pdf->Close();
$pdf->Output('unicode.pdf', 'F');

Примеры PDF-файлов сгенерированных классом: pdf1, pdf2, pdf3.

Скачать UFPDF2.
Для работы класса необходим класс UFPDF. Скачать UFPDF.
Документация по FPDF


Комментарии

  1. (#)   Yuriy:

    увы, появляется ошибка; "FPDF error: Could not include font definition file". Не смортя на то что файлы лежат на месте и права выставленны максимальные.

  2. (#)   szpargalki:

    А вы генерировали файлы шрифтов? В архиве с UFPDF есть файлик README.txt - в нем инструкция по генерации.

    Для примера, использующего шрифт LucidaSansUnicode, нужно выполнить следующие действия:
    1. берем файл lsansuni.ttf
    2. копируем его в каталог ufpdf/tools
    3. выполняем команду $ ttf2ufm -a -F lsansuni.ttf
    4. затем команду $ php -q makefontuni.php lsansuni.ttf lsansuni.ufm
    5. копируем сгенерированные lsansuni.php, lsansuni.z and lsansuni.ctg.z в каталог ufpdf/font

    Все, пример должен работать.

  3. (#)   Артем:

    Помогите пожалуйста, делаю все по мануалу, уже второй шрифт генерирую, но пишет:
    Unsupported font type: TrueTypeUnicode
    Не знаю, что делать, не могли бы выложить исходники своих шрифтов?

  4. (#)   szpargalki:

    Скачайте этот архив http://goo.gl/HO5pjq

    Там рабочий пример для трех шрифтов DroidSans, DroidSansMono и LaudatioC. Попробуйте у себя и сообщите о результатах.

  5. (#)   Андрей:

    Помогите, пожалуйста, разобраться. Почему-то не получаются внешние ссылки.

    Кстати в Ваших примерах (pdf1, pdf2, pdf3) ссылки тоже не рабочие...

  6. (#)   dimka:

    Не понял. Какие внешние ссылки?
    Вы имели ввиду URL внизу страницы?

  7. (#)   greynemo:

    А как подключать шрифты на Linux? Эти команды в терминале не пойдут ...

  8. (#)   dimka:

    Проблема только с ttf2ufm. Есть бинарник под виндовс, а под вашу систему его нет.

    В архиве с UFPDF есть каталог с исходниками ttf2ufm. Там лежит файл winbuild.bat. Создаем по аналогии файл linuxbuild.sh:

    #!/bin/sh

    gcc -c bdf.c
    gcc -c ttf2pt1.c
    gcc -c pt1.c
    gcc -c ttf.c
    gcc -c t1asm.c
    gcc -c bitmap.c
    gcc -o ttf2ufm ttf2pt1.o pt1.o t1asm.o ttf.o bdf.o bitmap.o -lm
    gcc -o t1asm -DSTANDALONE t1asm.c

    Даем ему права на запуск chmod +x linuxbuild.sh
    Запускаем и получаем скомпилированный по вашу систему ttf2ufm.

    Дальше все по инструкции, приведенной выше.

  9. (#)   Евгений:

    День добрый!!!
    метод Output() вторым параметром принимает куда выводить I,F,D,S

    у меня из 4-х параметров работает только F
    I - выводит иероглифы
    При параметре D файл скачивается, но при открытии выдает ошибку
    S - вообще ничего не происходит
    В чем может быть проблема?

  10. (#)   Евгений:

    У меня стоит задача сгенерировать с помощью PHP PDF файл из изображения SVG. Сначала попробовал класс FPDF, но он не поддерживает генерацию PDF файла из изображения SVG, тогда обратился к другому классу TCPDF, он отлично генерирует PDF из изображений SVG, но о возникла следующая проблема – все русские буквы в изображение SVG, при генерации PDF отображаются вопросительными знаками. Как побороть данную проблему? Помогите, пожалуйста.


  11. (#)   dimka:

    Может проблема в шрифтах?

    Можно ли ему подсунуть другой какой-либо файл шрифтов и попробовать сгенерировать pdf?


  12. (#)   Evil:

    Поставил FPDF – нет поддержки UTF,
    Поставил UFPDF – начались ошибки со шрифтами,
    Поставил UFPDF2 – понеслась дальше Warning: filesize() [function.filesize]: stat failed for font/font/times.php in F:\путь\fpdf\fpdf.php on line 1170
    FPDF error: Font file not found

    Походу чем дальше тем хуже.


  13. (#)   Владимир:

    Поставил ufpdf2 вывел кириллицу и картинки – полет нормальный.
    По ходу были несколько ворнингов которые легко исправил.
    Спасибо большое!


  14. (#)   vasena:

    Пришлось маленько «поломать» голову. В результате получился класс UFPDF2, который является расширением UFPDF и в котором корректно работает метод MultiCell.
    Хрен там, он корректно работает только для двухстрочного текста, для трех строк он начинает выдавать пустые строки в середине (т.е. есть первая и последняя строка видны, а между – пусто) лечится это заменой функции usubstr на корректную:
    function usubstr($arr, $from, $to=false){
    if (!$to) $to = count($arr) – $from;
    $res = “”;
    for($i=0; $i<$to; $i++) {$res .= $this->code2utf($arr[$from + $i]);}
    return $res;
    }
    Далее – видим что теперь текст появился, однако если у вас более чем 3 строки, то начинает проявлятся другой баг, а именно начинают пропадать буквы в конце строки и слова ломаться не по пробелам. Как я выяснил, автор заплатки решил поставить лишнюю заплатку, а именно везде где использовался while для перебора символов в тексте заменил на foreach, чтобы убрать по его мнению лишнюю строку $c=$s[$i]; а это черевато, т.к. теперь мы не контролируем индекс, а значит перенос у нас проиходит там где хочется( foreach’у). Лечится это заменой всех фраз foreach($s as $c) на while($i<count($s)) и возвратом из комментариев $c=$s[$i];
    Пока все. Найду еще что-то напишу.
    PS кстати, с поддержкой UTF-8 вы теряете поддержку копирования текста (по крайней мере для родного Adobe Reader, хотя Foxit нормально копирует)


  15. (#)   Tvolod:

    А не могли бы обновить ссылку на UFPDF или залить его на файл-шару? Ссылка из текста не работает, поиск по сайту acko.net ничего не дал.
    Спасибо за статью!


  16. (#)   Tvolod:

    Новая ссылка на UFPDF такая: http://acko.net/blog/ufpdf-unicode-utf-8-extension-for-fpdf/


Оставить комментарий

Ответ на PHP. Создание PDF-файлов «на лету» в кодировке UTF-8