There are several ways of serving static files from Zope. The simplest way is to just do something like this:


size = os.stat(file_path)[stat.ST_SIZE]
REQUEST.RESPONSE.setHeader('Content-Type','image/jpeg')
REQUEST.RESPONSE.setHeader('Content-length',int(size))
return open(file_path, 'rb').read()

The disadvantage with this is if the file is say >1Mb, the whole 1Mb needs to be loaded into RAM before it can be sent. This is surely garbage collected afterwards but if you serve many of these at the same time, there's obviously the risk that the RAM gets too full.

The alternative is to use filestream_iterator from the ZPublisher which is an iterator that sends out chunks of the file at a time. Note that to use the filestream_iterator you must set the Content-Length header first. Here's how to use it:


from ZPublisher.Iterators import filestream_iterator
...
size = os.stat(file_path)[stat.ST_SIZE]
REQUEST.RESPONSE.setHeader('Content-Type','image/jpeg')
REQUEST.RESPONSE.setHeader('Content-length',int(size))
return filestream_iterator(file_path, 'rb')

I did a little unofficial benchmark to test if there's any speed difference between the two approaches. I'm currently only interested in serving photographs (jpg) in this app and I'm sure other results would be found if you did bigger filesystem files. These jpgs are in average about 200 Kb. During the course of writing this I tought I'd also try using sendfile as well to see if that makes it any faster:


Serving 526 jpgs with...
function             average total time (5 tests)
  open()               5.07750701904
  filestream_iterator  4.32704296112
  sendfile             4.431672620774

Interesting. Using filestream_iterator shaves off a few milliseconds but it's over many many servings. Conclusion, the benefit of filestream_iterator is not speed, it's RAM (un)usage.

Note. From reading the LocalFS source code I noticed that they only bother with the filestream_iterator if the filesize is greater than 128Kb. I copied that too into my app now but don't understand why. Is there a disadvantage of serving tiny files with filestream_iterator() Anybody?

Worth noting that sendfile wasn't any faster but I suppose you only see a speed boost with sendfile on much larger files.

Comments

Your email will never ever be published.

Related posts