How to return an image in an HTTP response using CherryPy

I have the code that Cairo ImageSurface generates and I expose it like this:

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

This does not work (browsers report that the image has errors).

I tested that surface.write_to_png('test.png') works, but I'm not sure what to unload the data to return it. Am I guessing some kind of file object? According to pycairo documentation , get_data() returns a buffer. I also tried:

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

In addition, is it better to create and hold this image in memory (for example, I'm trying to make it) or write it to disk as a temporary file and serve it from there? I need an image only once, then it can be discarded.

+7
python cherrypy cairo
source share
4 answers

Add these imports:

 from cherrypy.lib import file_generator import StringIO 

and then follow these steps:

 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) 

Additionally, if you are using a stand-alone file (i.e. it is not part of the web page) and you do not want it to be displayed in the browser, but rather viewed as a file for saving to disk, then you need one more header:

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

Besides, is it better to create and hold this image in memory (for example, I'm trying to make it) or write it to disk as a temporary file and file it from there? only i need the image once, then it can be discarded.

If the only thing you want to do is serve this file in a browser, there is no reason to create it on disk on the server. On the contrary, remember that access to the hard drive leads to poor performance.

+15
source

You fail due to the incomprehensibility of surface.get_data() . You are trying to return a mime-type image/png , but surface.get_data() returns a monotonous bitmap (not a Widnows.BMP bitmap file with a header), which is a simple image dump from the "virtual screen" (surface)

Like this:

 0000010000
 0000101000
 0001000100
 0010000010
 0001000100
 0000101000
 0000010000
+1
source

Have you tried return str(surface.get_data()) ?

0
source

Try this for a file in memory approach

 return StringIO.StringIO(surface.get_data()) 
0
source

All Articles