如何在CherryPy中返回HTTP响应的图像
我有一段代码可以生成一个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 个回答
0
试试这个“内存中的文件”方法
return StringIO.StringIO(surface.get_data())
2
你遇到问题是因为你不理解 surface.get_data()
的工作原理。你想要返回的文件类型是 image/png
,但是 surface.get_data()
返回的是普通的位图图像(并不是带有头信息的 Windows 位图文件 .BMP),它只是从“虚拟屏幕”(表面)中提取的普通图像数据。
就像这样:
0000010000 0000101000 0001000100 0010000010 0001000100 0000101000 0000010000
18
添加这些导入:
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"'
另外,创建并在内存中保存这个图像(就像我现在尝试做的那样)是否更好,还是把它写入磁盘作为临时文件,然后从那里提供?我只需要这个图像一次,之后就可以丢弃了。
如果你唯一想做的就是把这个文件提供给浏览器,那么在服务器上创建这个文件并没有必要。相反,要记住,访问硬盘会带来性能上的损失。