Kung Fu Kung Fu

Fujian White Crane Kung Fu

Zope Zope

What I have and am doing with Zope

Photos Photos

Photoalbum, both old and new.

Receptsamlingen Receptsamlingen

In Swedish only. About my "Collection of Recipes" website.

Contact me Contact me

My contact details and how to contact me.

  Mobile version of this page Mobile version of this page


 

Zope Image to filesystem image

filesystem, zodb, chunks, 2^16, 65kb, stream, blob, sascha welter, betabug, #zope, irc

16th of March 2007

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:

 >>> imgobj.meta_type
 Image
 >>> open(temp_file_path,'wb').write(imgobj.data)

...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)


Comment

mike - 23rd May 2007  [«« Reply to this]
This is pretty neat. I have a similar issue with trying to use a Python script to return a .mp3 from a Zope file object. Whenever the script is called it *renders* the .mp3 instead of passing the data.

Do I need to do something similar to your script to make this work properly?
Peter Bengtsson - 9th July 2007   [«« Reply to this]
I doubt that it *renders* the mp3 file. Perhaps you mean that it starts playing or something. There's a solution to that, set the Content-Type to something like "application/octet-stream"
 
Name:
Email:
hide my email address.

Your email address will be encoded to prevent email-extraction spiders from reading it so you won't get spammed if you decide to show your email address.