Как вернуть изображение в HTTP-ответе с CherryPy - PullRequest
7 голосов
/ 17 июня 2010

У меня есть код, который генерирует Cairo ImageSurface, и я выставляю его так:

def preview(...):
    surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
    ...
    cherrypy.response.headers['Content-Type'] = "image/png"
    return surface.get_data()
preview.exposed = True

Это не работает (браузеры сообщают, что на изображении есть ошибки).

Я проверил, что surface.write_to_png('test.png') работает, но я не уверен, что для сброса данных, чтобы вернуть его.Я предполагаю какой-нибудь файл-подобный объект?Согласно документации pycairo , get_data() возвращает буфер.Я также сейчас попробовал:

tempf = os.tmpfile()
surface.write_to_png(tempf)
return tempf

Кроме того, лучше создать и сохранить этот образ в памяти (как я пытаюсь сделать) или записать его на диск в качестве временного файла и обслуживать егооттуда?Мне нужно изображение только один раз, тогда оно может быть отброшено.

Ответы [ 4 ]

17 голосов
/ 21 июня 2010

Добавьте этот импорт:

from cherrypy.lib import file_generator
import StringIO

и затем выполните следующее:

def index(self):
    surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
    cherrypy.response.headers['Content-Type'] = "image/png"

    buffer = StringIO.StringIO()
    surface.write_to_png(buffer)
    buffer.seek(0)

    return file_generator(buffer)

Дополнительно, если вы обслуживаете автономный файл (т. Е. Он не является частью веб-страницы).) и вы не хотите, чтобы он отображался в браузере, а обрабатывались как файл для сохранения на диске, тогда вам нужен еще один заголовок:

cherrypy.response.headers['Content-Disposition'] = 'attachment; filename="file.png"'

Кроме того, лучше создатьи держать это изображение в памяти (как я пытаюсь сделать) или записать его на диск в качестве временного файла и отправить его оттуда?Мне нужно только одно изображение, затем оно может быть удалено.

Если единственное, что вы хотите сделать, - это передать этот файл в браузер, то нет причин создавать его на диске насервер.Наоборот, помните, что доступ к жесткому диску снижает производительность.

1 голос
/ 25 января 2011

Вы терпите неудачу из-за непонимания работы surface.get_data(). Вы пытаетесь вернуть MIME-тип image/png, но surface.get_data() возвращает обычное растровое изображение (не файл растрового изображения Windows .BMP с заголовком), которое это дамп простого изображения с "виртуального экрана" (поверхность)

Как это:

0000010000
0000101000
0001000100
0010000010
0001000100
0000101000
0000010000
0 голосов
/ 18 июня 2010

Попробуйте это для подхода "файл в памяти"

return StringIO.StringIO(surface.get_data())
0 голосов
/ 18 июня 2010

Вы пробовали return str(surface.get_data())?

...