Today I bumped into a nasty challenge when trying to copy a Zope image from ZODB to the filesystem. The reason why it wasn't easy was that Zope splits the file up into chunks if it's upload size is more than 65Kb (2^16 bytes) which I guess it does for being able to "stream" the file back into the browser when viewing the image instead of sending one large blob.
So, this didn't work:
...if the data is big because sometimes
imgobj.data is a string (the binary data) and sometimes is a
ImplicitAcquirerWrapper that you have to iterate over.
That's when Sascha Welter stepped up on the
#zope channel on IRC with a snippet of code that does it properly:
def write_zodb_file_to_tempfile( source, temp_file ): """ Write data from a file from the ZODB / Zope to a tempfile on the filesystem. input: - source (a zope object, not just a string with the object id!!) - temp_file (a writable file object) """ data = source.data if isinstance(data, StringType): #StringType temp_file.write( str(data) ) else: (start,end) = (0,source.getSize()) pos = 0 while source.data is not None: l = len(data.data) pos = pos + l if pos > start: # We are within the range lstart = l - (pos - start) if lstart < 0: lstart = 0 # find the endpoint if end <= pos: lend = l - (pos - end) temp_file.write(data[lstart:lend]) break # Not yet at the end, transmit what we have. temp_file.write(data[lstart:]) data = data.next temp_file.flush() temp_file.seek(0, 0)