Monday, March 19, 2007

Sendfile Patch for Zope2

I've put together a patch for Zope that allows code to use the sendfile system call to transfer data out of Zope.

As this requires a file object, it's only available for use from trusted code, so that means inside a Product or an External method.

The good news is, that it's fairly easy to write an External method that does something useful like serve contents from a directory.

Here's an example external method that serves files from '/shared/images'

import os
directory = '/shared/images'

def Image(self, filename):
newPath = os.path.join(directory, filename)
if not os.access(newPath, os.F_OK|os.R_OK):
self.REQUEST.RESPONSE.setStatus(404)
return ''
f = open(newPath, 'rb')
self.REQUEST.RESPONSE.sendfile(f, content_type='image/jpeg', other_headers = {'Content-Disposition', 'inline;filename=%s'%(filename))
f.close()
return ''

It uses the sendfile wrapper module from here.

It gives you a speed up of 2-3 times serving content out of Zope from the filesystem.
I also have a patch for ExternalFile to let this use the sendfile patch.

You can get the code and the patch from zope.org

2 comments:

mork said...

hi
very interesting
i am not able to use it though...
i created the external method, and a page template where i may call it from a python script.
The result is... nothing.
Would you please provide a step-by-step guide?
thanks

marco

TJ said...

If you don't have the sendfile patch installed, you can replace the self.REQUEST.RESPONSE.sendfile() call, with;

self.REQUEST.RESPONSE.write(f.read())

Also, you should navigate directly to your external method, to cause the download, not call it from a template.