Дали мне одно задание - используя API одного сервиса для получения исходных данных, автоматически заполнять бланки для Почты России, чтобы быстро отправлять их на печать. Грубо говоря, написать импровизированного бота, который будет с этим разбираться.
Услышав "PDF", я порадовался и подумал, что "для него уж точно кучу всего написали, проще некуда, найду что-нибудь". Но не тут-то было!
Поискав на Гитхабе, нашёл оригинальную библиотеку pdf-fill-form, написанную на NodeJS. Потратил достаточно времени на разборки с тем, дабы заставить её работать, но ничего хорошего из этого не вышло. Русские символы никак не отображались. Вместо них - кракозябры, либо пустота.
Посмотрел в сети, и выяснилось, что проблема библиотеки - в зависимости от libpoppler. Баг в poppler'е затрагивает многие другие приложения, например, Evince. И проблему в последнем до сих пор можно увидеть без особых усилий.
https://bugs.launchpad.net/ubuntu/+source/evince/+bug/1288182
Представьте себе, баг по этой ссылке висит с 2008 года, но так и не исправлен!
----------
Идём по Гитхабу дальше. Все остальные репозитории с нужным мне делом представлены обёртками для программного пакета pdftk.
pdftk имеет множество фич. Можно даже сказать, что это самая популярная вещь для автоматической обработки. Он может "инспектировать" PDF-файлы, декомпилировать их, изменять внутренности и так далее. Работает на основе файлов FDF и XFDF (XML-версия формата). Туда записываются данные для заполнения в декларативном виде, затем скармливаются pdftk, и тот выдаёт заполненный результат.
Но здесь я опять потерпел неудачу. Кириллица снова отказывается отображаться. В багтрекере уже появлялись люди с похожими проблемами, но их мягко посылали. Были люди, которые предлагали обходные пути вроде дополнительных параметров, но здесь они не помогли.
В чём же проблема с ним?
Оказывается, pdftk полностью перестраивает шрифты в выходном документе, полурандомным образом удаляя некоторые из них. Были товарищи, которые советовали подключать позднее свои шрифты через костыли к полям форм, но этот способ слишком ненадёжный и неочевидный. Баг до сих пор толком не исправлен, хотя поддержка юникода, говорят, улучшилась в pdftk с 2 версии (которую я и использовал). Пользователям из России говорят, что эта самая поддержка в pdftk сделана с существенными ограничениями.
-----------
Где же, наконец, простое и рабочее решение для автозаполнения PDF-форм?
Вот оно:
https://sourceforge.net/projects/pdfformfiller2/?source=directory
Использует библиотеку iTextPdf 5 версии, написано на Java.
Установка после распаковки zip-а:
1. Требуется OpenJDK 7 или 8
2. Надо скачать iTextPdf отсюда:
https://github.com/itext/itextpdf/releases/tag/5.5.10
3. Затем распаковать jar-файлы и положить их в lib/ к pdfformfiller-у
4. Компилируем обёртку
javac -d . -cp lib/itextpdf-5.5.10.jar PdfFormFiller.java
5. Делаем скрипт для запуска утилиты
java -classpath .:lib/itextpdf-5.5.10.jar PdfFormFiller.PdfFormFiller $1 $2 $3 etc
Всё, готово к использованию. Программа принимает в качестве ввода файл с названиями полей ввода и внешний шрифт (в формате ttf), которым надо их заполнять. Может брать данные в том числе из stdin.
Кстати, насчёт остального. Для выяснения, какие шрифты есть в документе, пригодится cli-утилита pdffonts из состава poppler.
Чтобы узнать id полей ввода в документе, можно использовать pdftk file.pdf dump_data_fields, либо сам pdfformfiller, в котором это предусмотрели (см. справка).