Как вернуть изображение в HTTP-ответе с помощью CherryPy
У меня есть код, который генерирует Каир 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 ответа:
Добавьте следующие импортные операции:
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"'
Также, лучше ли создавать и удерживать этот образ в памяти (как я пытаюсь делать) или записать его на диск в качестве темпа подать и подать его оттуда? Я только нужен образ один раз, тогда это может быть отброшенный.
Если единственное, что вы хотите сделать, это передать этот файл браузеру, нет никаких причин создавать его на диске на сервере. Совсем наоборот-помните, что доступ к жесткому диску приводит к снижению производительности.
Вы терпите неудачу из-за непонимания работы
surface.get_data()
. Вы пытаетесь вернуть mime-типimage/png
, ноsurface.get_data()
возвращает простое растровое изображение (не является растровым файлом Windows .BMP с заголовком) который это обычный дамп изображения с "виртуального экрана" (surface)Вот так:
0000010000 0000101000 0001000100 0010000010 0001000100 0000101000 0000010000