Продолжая тему о работе с PDF в Ubuntu расскажу, с какими сложностями я столкнулся, когда стал решать задачу о внесении метаданных в PDF документ. Нужно всего лишь в определенные страницы сосканированного проекта добавить скрытые пометки, которые помогли бы в поиске этих страниц (а это, как правило, чертеж какой-нибудь).
Можно внести информацию о всем документе с помощью упомянутой
ранее утилиты pdftk таким образом:
$ pdftk file.pdf dump_data output metainfoВ файл metainfo запишется информация следующего характера:
InfoKey: Title
InfoValue: untitled
InfoKey: Producer
InfoValue: ReportLab http://www.reportlab.com
InfoKey: Author
InfoValue: anonymous
InfoKey: Subject
InfoValue: unspecified
InfoKey: CreationDate
InfoValue: 20081217165436
PdfID0: ebd25ab8427fa1508e9924204f74b274
PdfID1: ebd25ab8427fa1508e9924204f74b274
NumberOfPages: 1Соответственно, InfoKey - ключ, InfoValue - значение. Думаю, тут все понятно, двинем дальше. Теперь мы можем поменять значения ключей и сохранить файл, а потом изменить значение метаданных в нашем PDF файле:
$ cp file.pdf file.cp.pdf
$ pdftk file.cp.pdf update_info metainfo output file.pdf
$ rm file.cp.pdf Зачем такой огород? А затем, что pdftk умеет сохранять метаданные только в другой файл, поэтому мы создаем временный, потом обновляем его данные, сохраняя в исходный, и удаляем временный. Вот петрушка... Но это еще цветочки. Ягодки в том, что если прописать в файле с метаданными текст на русском языке, то evince покажет его крякозябрями, а если попробовать извлечь инфо из обновленного файла, то увидим вместо наших русских буковок вот примерно такое: "ᅠテ", что совсем не соответствует желаемому. К тому же, так задача пометок отдельных страниц не решается. Копаем дальше.
Эта же утилита умеет пристегивать к отдельным страницам PDF документа файлы. Во! Это уже что-то! Составляем файл с нужными данными (рекомендуется HTML или Excel файл, потому что тогда Adobe Reader адекватно среагирует, то есть откроет его). Пристегиваем файл с информацией к первой странице PDF:
$ cp file.pdf file.cp.pdf
$ pdftk file.cp.pdf attach_files to_page 1 output file.pdf
$ rm file.cp.pdfНу наконец-то. Неужели это все? Проблема решена? Щазз! Мы только подходим к трудностям. Ведь нам надо как-то извлечь оттуда прикрепленные файлы. А вот тут нас ждет 2 проблемы.
1) Не нашел (а я искал!) в pdftk возможности извлечения файлов выборочно, из определенных страниц, только все скопом:
$ pdftk file.pdf unpack_files output unpack/Здесь все файлы извлекаются в папку unpack, если она конечно существует, иначе будет error. Одноименные файлы перезаписываются.
2) Все шло более-менее гладко, пока я экспериментировал с файлами PDF журнала LinuxFormat. И картина изменилась, когда дело дошло до настоящих чертежей, отсканированных на нашем широкоформатном сканере. Нет, записывать метаданные и даже прикреплять файлы к страницам получалось нормально, но вот когда я попытался извлечь прикрепленные файлы я увидел примерно вот что:
Unhandled Java Exception:
java.lang.NullPointerException
at java.lang.String.toLowerCase(libgcj.so.81)
at java.lang.String.toLowerCase(libgcj.so.81)
at com.lowagie.text.pdf.PdfEncodings.convertToBytes(pdftk)Все это в различных вариациях на тему некоего libgcj.so.81. Из всего этого я сделал пару выводов: а) pdftk написана на Java, хотя бы частично и б) проблема связана с текстовой информацией в файле.
Вот тут я был озадачен. Текстовой информации в файле не подразумевалось никакой, только одно-единственное изображение. Ладно бы там была какая-нибудь кириллица, и он на кодировках спотыкался. Но ведь неоткуда там тексту взяться! И тем не менее, файлы сторонние обрабатывались на ура, а мои сосканированные - ни в какую.
Сейчас поведаю, через какие извращения я прошел, чтобы превратить мой PDF в корректно обрабатываемый pdftk. Все это я делал на Python, о библиотеках, которые тут приводятся, я говорил чуть
раньше.
Приготовились смеяться? Начали!
[файл workpdf.py]#!/usr/bin/env python
# -*- coding: utf-8 -*-# Допустим, что файл называется так:
filename="00.pdf"import os
from reportlab.pdfgen import canvas
from reportlab.lib.units import cm
from reportlab.pdfbase import pdfmetrics, ttfonts
from pyPdf import PdfFileReader# Полчение размера страницы в пикселах
input = PdfFileReader(file(filename, "rb"))
p=input.getPage(0)
width = p.mediaBox[2]
height= p.mediaBox[3]# Починка файла (чтобы convert не ругался)
os.system("pdftk "+filename+" output 01a.pdf")
# Конвертирование его в картинку
os.system("convert 01a.pdf workpdf_temp_file.jpg")# Удаление ненужной копии
os.system("rm 01a.pdf "+filename)# Задаем настройки шрифта
MyFontObject = ttfonts.TTFont('Verdana', '/usr/share/fonts/truetype/msttcorefonts/tahoma.ttf')
pdfmetrics.registerFont(MyFontObject)# Создаем основу нового PDF
MyCanvas = canvas.Canvas("test.pdf")# Задаем размеры, равные исходному файлу, добавляем шрифты и тестовый текст
# Не знаю зачем, но видимо pdftk очень хочет найти текст в файле
MyCanvas.setPageSize((width, height))
MyCanvas.setFont("Verdana", 40)
MyCanvas.drawString(-100, -100, "test")# Добавляем картинку из исходного файла
MyCanvas.drawImage("workpdf_temp_file.jpg",0,0)# Завершаем и сохраняем файл
MyCanvas.showPage()
MyCanvas.save()# А теперь барабанная дробь: прикрепляем файл и открепляем его без ошибок!
print os.system("pdftk test.pdf attach_files info to_page 1 output "+filename)
print os.system("pdftk "+filename+" unpack_files output unp/")# И удаляем никому не нужные теперь файлы
os.system("rm test.pdf workpdf_temp_file.jpg")Ну как? Животики надорвали? А главной проблемы - извлечения отдельно взятого файла от отдельно взятой страницы многостраничного PDF документа - я так и не решил. Пока не решил. А вы?