Как сделать веб-сервис для конвертации файлов Excel, Word, TXT и других в PDF в режиме «как вижу»

в 10:31, , рубрики: Excel, Веб-разработка, Программирование, системное администрирование, метки:

Откуда пошла дурацкая привычка сохранять счета, бухгалтерские и финансовые документы в формате MS Excel? Зачем хранить и передавать документы, предназначенные для печати в формате электронной таблицы, если есть специальный формат PDF? Однако, во всех бухгалтерских программах документы в первую очередь обязательно экспортируются в MS Excel и уже потом предлагаются альтернативные способы сохранения документов. От сюда и возникла задача: пусть бухгалтер сохраняет свои документы как хочет, но клиент должен получить их в формате PDF и обязательно точно в том образе, который бухгалтер сваял в шаблоне MS Excel.
В качестве бухгалтерской программы мы использовали бесплатную ВС: Бухгалтерию. (По правде сказать из этой программы можно сразу сохранять документы в PDF, но раз сказали excel, значит – excel.)
Бухгалтер выгружает XLS-файл в определенный каталог на диске, откуда мы должны его забрать, перевести в PDF и сохранить в другой каталог. Все это должно быть реализовано в виде веб-сервиса, то есть клиент должен увидеть и иметь возможность скачать свои pdf-документы в «Личном кабинете» на сайте.

Пути решения:

Первое, что захотелось сделать, – это отыскать готовую библиотеку для PHP или Perl и прямо «на лету» конвертировать файлы.
Такие библиотеки для работы с форматом Excel действительно нашлись, например: PHPExcel, PHPExcelReader, Spreadsheet::ParseExcel и др.
Эти библиотеки действительно хорошо работают, но делают именно то, для чего предназначены: выискивают данные в электронной таблице Excel и оперируют с ними.
Нам же нужно совсем иное – получить экселевскую таблицу в виде как для печати, со всеми картинками с печатями и подписями, с форматами шрифтов, и ячеек.

Второй вариант решения — виртуальный принтер. Суть его в том, что мы открываем файл в подходящей программе и отправляем его на печать, но не на настоящий принтер, а – на виртуальный, который вместо бумаги сохранит в файл, сначала в постскрипт формате ps, а потом сделает из него файл PDF.
Поскольку система ко всему еще и должна функционировать как веб-сервис, я выбрал в качестве платформы Linux с Apache. А в качестве программы, которая умеет открывать все файлы MS Office – бесплатный OpenOffice.org 3.4

Итак, что делаем:

Устанавливаем OpenOffice. В руководстве по по установке конвертера PyODConverter предлагают устанавливать версию OpenOffice.org 2.4 обязательно -headless, но я просто установил OpenOffice.org 3.4 из репозитория и все получилось.
После установки я попробовал запустить программу, но система отказалась, захотев еще Java Runtime Environment. А нужен ли он? Оказалось, что нет. И запускать OpenOffice целиком, чтобы отправить файл на виртуальный принтер вовсе ни к чему. У программы есть прекрасный конвертер в pdf, который легко вызвать из командной строки.

Делается это так:

Создаем конвертер в PDF

Создаем bash-файл, например с именем converter.sh

<code>

<source lang="bash">
#!/bin/bash

# Проверяем где установлен OpenOffice.org и PYTHON. 
#Поправьте пути вручную, если они отличаются на вашей системе

OOFFICE=`ls /usr/bin/openoffice.org3 /usr/bin/ooffice /usr/lib/openoffice/program/soffice | head -n 1`
OOOPYTHON=`ls /opt/openoffice.org*/program/python /usr/bin/python | head -n 1`

if [ ! -x "$OOFFICE" ]
then
 echo "Could not auto-detect OpenOffice.org binary"
 exit
fi

if [ ! -x "$OOOPYTHON" ]
then
 echo "Could not auto-detect OpenOffice.org Python"
 exit
fi

echo "Detected OpenOffice.org binary: $OOFFICE"
echo "Detected OpenOffice.org python: $OOOPYTHON"

# Reference: http://wiki.services.openoffice.org/wiki/Using_Python_on_Linux
# If you use the OpenOffice.org that comes with Fedora or Ubuntu, uncomment the following line:
# export PYTHONPATH="/usr/lib/openoffice.org/program" 

# If you want to simulate for testing that there is no X server, uncomment the next line.
#unset DISPLAY

# Kill any running OpenOffice.org processes.
killall -u `whoami` -q soffice

# Это важная строчка: программа пытается скачать из сети скрипт на языке Python, который как раз #нужен OpenOffice для конвертации файлов. Если все хорошо, то после запуска  converter.sh в #каталоге появится файл с именем DocumentConverter.py. 
#Если не получилось — скачайте файл  DocumentConverter.py 
#вручную по адресу ниже и поместите в один каталог с этим скриптом.
#Проверьте чтобы порт в скрипте был указан 8100
test -f DocumentConverter.py || wget http://www.artofsolving.com/files/DocumentConverter.py

# Start OpenOffice.org in listening mode on TCP port 8100.
$OOFFICE "-accept=socket,host=localhost,port=8100;urp;StarOffice.ServiceManager" -norestore -nofirststartwizard -nologo -headless  &

# Wait a few seconds to be sure it has started.
sleep 5s

# Здесь мы перечисляем имена файлов, которые хотим конвертировать: 
#Имя исходного файла — в какой файл конвертируем. 
# Самое приятно, что конвертировать можно не только в PDF, но и в любой формат, 
#поддерживаемый OpenOffice.org
# 
# Из MS PowerPoint во Flash
$OOOPYTHON DocumentConverter.py sample.ppt sample.swf

#Из Excel в PDF
$OOOPYTHON DocumentConverter.py sample.xls sample.pdf

# Close OpenOffice.org.
killall -u `whoami` soffice

#---------------------------------------------------- 

</source>
</code>

Выставьте права для запуска скрипта converter.sh (755)
Поместите в один каталог с этим скриптом (converter.sh) Excel-файл под именем sample.xls, запустите скрипт converter.sh и в каталоге появится файл sample.pdf, который будет копией печатного вида экселевского файла.

Пол-дела сделано. Теперь нам нужно организовать процесс конвертации в виде веб-сервиса.
Можно, конечно, поместить файл converter.sh в каталог /cgi-bin/ Apache и запускать сразу его, но тут уже начинаются задачи обеспечения безопасности. К вопросу безопасности такого сервиса нужно подойти очень тщательно, ведь мы собираемся передавать скрипту неизвестные файлы и разрешать ему сохранять неизвестно что на диске.
Правильный подход – это разместить файл converter.sh выше DOCUMENT_ROOT Apache, а обращаться к нему через скрипт-посредник, например, на perl, который будет лежать в каталоге /cgi-bin/ и тщательно проверять все параметры, передаваемые в converter.sh.

Какие обнаружились проблемы, после реализации сервиса конвертации.
Оказалось, что Linux не понимает файлы с именами русскими буквами в кодировке windows-1251. Что тут можно сделать:
1. Уговорить бухгалтера сохранять файлы с латинскими именами (сложно)
2. Конвертировать имя файла в utf-8 при загрузке в каталог (вполне реально)
3. Реализовать аналогичный сервис под Windows – Apache (попробую)

Под Windows конвертер реализовать тоже оказалось несложно

Я сделал так:
1. Скачал и установил LibreOffice 3.4
2. Скачал PyODConverter
3. Сохранил файл DocumentConverter.py в рабочем каталоге, например, C:test
4. Поменял в файле DocumentConverter.py константу DEFAULT_OPENOFFICE_PORT = 8100 (по умолчанию там был указан другой порт)
5. Поместил в каталог C:test пробный файл для конвертации – test.xls

Теперь запускаем процесс конвертации.
Сначала запускаем OpenOffice в скрытом режиме. В командной строке (cmd) пишем:

"C:Program FilesLibreOffice.org 3.4programsoffice.exe" -headless -nologo -norestore -accept=socket,host=localhost,port=8100;urp;StarOffice.ServiceManager

Здесь важно, чтобы порт совпадал с DEFAULT_OPENOFFICE_PORT

Теперь запускаем конвертацию:
"C:Program FilesLibreOffice.org 3.4programpython" c:testDocumentConverter.py c:testtest.xls c:testtest.pdf

И в каталоге c:test обнаруживаем конвертированный файл PDF.

Вот и готов конвертер файлов xls, doc, docx, rtf, txt, odt, ott, sxw, stw, html, xml, в общем всего, что откроет OpenOffice.

Автор: EvJik

* - обязательные к заполнению поля