Pull to refresh

И ещё один способ генерации PDF

Reading time 4 min
Views 9K
Навеяно топиком о генрации PDF с помощью ghostscript и Inkscape.

Посмотрев на предложенный вариант, я вспомнил одно очень интересное решение, коим и хочу поделиться.

Итак, генерация PDF с помощью QT


Не буду повторяться о том что такое PDF, я думаю все и так в курсе. Сразу приступим к делу.

Что нам понадобится:



— Выделенные сервер с возможностью установки своих приложений на linux.
— Библиотека QT 4.4 с модулем qt-webkit. Это мозг нашего приложения.
— Иходный код или уже скомпилированый проект wkhtmltopdf. Это сердце нашего приложения.
— Xvfb Xvfb маленький заменитель Х-сервера. Ресурсов не кушает, но и ничего не показывает. Зато выполняет нужные нам функции.

Немного теории:



Мы собираемся генерировать PDF из HTML, отрендерив HTML страничку с помощью движка HTML-рендеринга webkit и отпечатав её на виртуальный PDF-принтер.

Подготавливаем систему:



1. Запускаем Xvfb для того что бы наше хоть и консольное приложение не требовало подклбючения к X11
#/usr/bin/Xvfb :0 -screen 0 1024x768x24 -ac

Вот тут надо бы прописать это дело в автозагрузку, но я не буду советовать так как линуксы у всех разные и вариантов это сделать много.

2. Я надеюсь что QT уже установлена в системе. А wkhtmltopdf скачан или скомпилирован собственноручно.
Установим его в /usr/bin/wkhtmltopdf

3. Тест.
#DISPLAY=":0.0" wkhtmltopdf habrahabr.ru habr.pdf

Должно заработать :)

Пишем оболочку.



Поскольку для написания моего текущего проекта во всю используется Zend Framework, то компонент будет являться эдаким расширением к нему.
Подробнее об этом можно написать целую статью. Буду надеяться что те, кто до сих пор не поковырялись в нём, наконец-то найдут в себе силы этим заняться.

Вот такой класс:
<?php

class Zfe_PDFGen {
    
    const 
DISPLAY ':1.0';
    const 
CACHEDIR '/application/cache/'// From Document Root
    
const EXEC '/usr/bin/wkhtmltopdf';
    
    private 
$_source;
    
    private 
$_destination;
    
    function 
Zfe_PDFGen($aSource$aDestination){
        
        
$this->setSource($aSource);
        
$this->setDestination($aDestination);

    }    
    
    public function 
setSource($aSource) {
        
$filename = new Zfe_Uuid();
        
$tmpfile $_SERVER['DOCUMENT_ROOT']. self::CACHEDIR $filename ".html";
        
file_put_contents($tmpfile$aSource);
        
$this->_source $tmpfile;
    }
    
    public function 
setDestination($aDestination) {
        
$this->_destination $_SERVER['DOCUMENT_ROOT']. $aDestination;
    }
    
    public function 
generate() {
        
$result '';
        
        
$exec sprintf('DISPLAY="%s" %s %s %s'self::DISPLAYself::EXEC$this->_source$this->_destination);
        
        
exec($exec$result); 
                
        
unlink($this->_source);
        
    }
    
}



Замечу, что для генерации имени файла используется Zfe_UUid (случайный уникальный идентификатор согласно RFC 4122), у вас его конечно не будет, но написать свой генератор, я думаю, не составит труда.

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

<?php
$fetchview 
= new Zend_View();
$fetchview->addScriptPath($this->view->getScriptPaths());
$result $fetchview->render('index/_mailpdfgen.phtml');
        
$data $result;

$PDF = new Zfe_PDFGen($data'/html/files/test.pdf');
        
$PDF->generate();



Вот, собственно, и всё


Чем это лучше/удобнее? Ну хотя бы тем что ПДФ теперь генерируется из «родного» и «понятного» для любого верстальщика формата.
А главное генерируемый ПДФ выглядит чертовски симпатично. Быстро работает.

Минусов, конечно, тоже хватает.
— Не все имеют свои сервера.
— exec()
— в шаблонах для ПДФок пути к картинкам в тегах и подобных, приходится писать полными или относительно файла шаблона. Что не совсем удобно.
Tags:
Hubs:
+4
Comments 14
Comments Comments 14

Articles