sorl-thumbnail с графическим редактором backend pdf/ ошибка преобразования изображения в Windows7
Я пытаюсь настроить приложение sorl-thumbnail django для предоставления эскизов pdf-файлов для веб-сайта, работающих на Windows Server 2008 R2 с веб-сервером Appache.
У меня был функционал sorl-thumbnail с бэкэндом PIL для генерации миниатюр jpeg-изображений - который работал нормально.
Так как PIL не может читать pdf-файлы, я хотел переключиться на графический интерфейс. Я установил и протестировал комбинацию graphicsmagick/ghostscript. Из командной строки
gm convert foo.pdf -resize 400x400 bar.jpg
генерирует ожидаемый эскиз JPG. Это также работает для создания эскизов JPG в JPG.
Однако при вызове из sorl-thumbnail ghostscript вылетает. В оболочке Python django (оболочка python manage.py) я использую низкоуровневую команду, описанную в документации sorl, и передаю экземпляр FieldFile (ff), указывающий на foo.pdf, и получаю следующую ошибку:
In [8]: im = get_thumbnail(ff, '400x400', quality=95)
**** Warning: stream operator isn't terminated by valid EOL.
**** Warning: stream Length incorrect.
**** Warning: An error occurred while reading an XREF table.
**** The file has been damaged. This may have been caused
**** by a problem while converting or transfering the file.
**** Ghostscript will attempt to recover the data.
**** Error: Trailer is not found.
GPL Ghostscript 9.07: Unrecoverable error, exit code 1
Обратите внимание, что ff указывает на тот же файл, который хорошо конвертируется при использовании gm convert из командной строки.
Я также попытался передать экземпляр ImageFieldFile (iff) и получить следующую ошибку:
In [5]: im = get_thumbnail(iff, '400x400', quality=95)
identify.exe: Corrupt JPEG data: 1 extraneous bytes before marker 0xdb `c:\users\thin\appdata\local\temp\tmpxs7m5p' @ warning/jpeg.c/JPEGWarningHandler/348.
identify.exe: Corrupt JPEG data: 1 extraneous bytes before marker 0xc4 `c:\users\thin\appdata\local\temp\tmpxs7m5p' @ warning/jpeg.c/JPEGWarningHandler/348.
identify.exe: Corrupt JPEG data: 1 extraneous bytes before marker 0xda `c:\users\thin\appdata\local\temp\tmpxs7m5p' @ warning/jpeg.c/JPEGWarningHandler/348.
Invalid Parameter - -auto-orient
Изменяя настройки обратного сорта, чтобы использовать заданный по умолчанию бэкэнд PIL, и повторяя команду для преобразования jpg в jpg, уменьшенное изображение генерируется без ошибок / предупреждений и доступно через кеш.
Кажется, что sorl копирует исходный файл во временный файл перед передачей его в gm - и проблема возникает в этой операции копирования.
Я нашел то, что я считаю операцией копирования в источниках sorl_thumbnail-11.12-py2.7.egg\sorl\thumbnail\engine \convert_engine.py, строки 47-55:
class Engine(EngineBase):
...
def get_image(self, source):
"""
Returns the backend image objects from a ImageFile instance
"""
handle, tmp = mkstemp()
with open(tmp, 'w') as fp:
fp.write(source.read())
os.close(handle)
return {'source': tmp, 'options': SortedDict(), 'size': None}
Может ли проблема быть здесь - я не вижу этого!
Будем очень благодарны за любые предложения о том, как преодолеть эту проблему! Я использую django 1.4, sorl-thumbnail 11.12 с memcached и ghostscript 9.07.
1 ответ
После некоторых проб и ошибок я обнаружил, что проблему можно решить, изменив режим записи с 'w' на 'wb', чтобы источники sorl_thumbnail-11.12-py2.7.egg\sorl\thumbnail\engine \convert_engine.py строки 47-55 теперь читаются:
class Engine(EngineBase):
...
def get_image(self, source):
"""
Returns the backend image objects from a ImageFile instance
"""
handle, tmp = mkstemp()
with open(tmp, 'wb') as fp:
fp.write(source.read())
os.close(handle)
return {'source': tmp, 'options': SortedDict(), 'size': None}
Я полагаю, что в файле convert_engine.py есть еще два места, где нужно сделать то же самое изменение. После этого команда gm convert смогла обработать файл.
Однако, так как мои PDF-файлы довольно большие многостраничные, я столкнулся с другими проблемами, наиболее важными из которых являются то, что метод get_image делает полную копию файла перед созданием эскиза. С файлами размером около 50 Мб это оказывается очень медленным процессом, и, наконец, я решил обойти sorl и вызвать gm напрямую. Миниатюра затем сохраняется в стандартном ImageField. Не так элегантно, но гораздо быстрее.