У меня есть код, который генерирует Каир 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
Кроме того, лучше создать и содержать это изображение в памяти (как, я пытаюсь сделать), или запишите это в диск как временный файл и служите ему оттуда? Мне только нужно изображение однажды, затем оно может быть отброшено.
Добавьте эти импорты:
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"'
Кроме того, лучше ли создать и удерживать это изображение в памяти (как будто я пытаюсь делать) или записать на диск в качестве временного файл и обслуживать его оттуда? только я нужно изображение один раз, тогда это может быть отброшен.
Если единственное, что вы хотите сделать, это передать этот файл браузеру, нет причин создавать его на диске на сервере.Напротив, помните, что доступ к жесткому диску снижает производительность.
Попробуйте это для подхода «файл в памяти»
return StringIO.StringIO(surface.get_data())