Jayesh
Jayesh

Reputation: 53345

Google App Engine BlobProperty returns stale content

I store thumbnail images in Google App engine entities as BlobStoreProperties. Over time thumbnails need to be updated, which I do by updating the content of these entities with fresh image data. However I found out that any subsequent retrieval of these images still returns the same old copy that was saved first time in the entity. It's surprisingly inconsistent behavior. I wrote a simple standalone code to verify this.

Here are two simple handlers and a model definition. SaveImageHandler saves the image to datastore and LoadImageHandler retrieves it.

from google.appengine.ext import db
import logging

class Image(db.Expando):
 data = db.BlobProperty(required=True)
 uid = db.StringProperty(required=True) 

class SaveImageHandler(webapp.RequestHandler):                                
  def post(self, uid):                                                        
    imgdata = self.request.POST.get('imgdata').file.read()                    
    logging.error('Saving %d bytes'%(len(imgdata)))                           
    image = model.Image(data=imgdata, uid=uid)                                
    image.put()                                                               

class LoadImageHandler(webapp.RequestHandler):                                
  def post(self, uid):                                                        
    image = model.Image.gql('WHERE uid = :1', uid).get()                      
    self.response.headers['Content-type'] = 'image/png'                       
    logging.error('Loading %d bytes'%(len(image.data)))                       
    self.response.out.write(image.data)    

def application():
  return webapp.WSGIApplication([
    ('/_thumbsave/(.*)', SaveImageHandler),
    ('/_thumbload/(.*)', LoadImageHandler),
  ],debug=False)

def main():
  util.run_wsgi_app(application())

if __name__ == '__main__':
  main()

I upload an image like this

curl -F "imgdata=@/tmp/img1.png" http://ubuntu.local:8000/_thumbsave/X

I retrieve the image

curl -d dummy=0 http://ubuntu.local:8000/_thumbload/X > Downloads/imgout.png

imgout.png and img1.png are same

Then I upload another image img2.png

curl -F "imgdata=@/tmp/img2.png" http://ubuntu.local:8000/_thumbsave/X

Then retrieve it in same way above. I expect now imgout.png to be same as img2.png. But instead I find that it's still the same old img1.png. Thus the Image query, returned stale object. The log statements that print the length of image, also verify that the image returned second time is not the updated one.

What's going wrong here?

Upvotes: 1

Views: 719

Answers (1)

Chris Farmiloe
Chris Farmiloe

Reputation: 14185

In your SaveImageHandler you are creating a new Image entity each time you POST your image data, then you are just fetching the first image with that uid in your LoadImageHandler

Change it to 'find or create' the image like:

class SaveImageHandler(webapp.RequestHandler):
  def post(self, uid):
    image = Image.all().filter("uid =", uid).get()
    if not image:
        image = model.Image(uid=uid)
    image.data = self.request.POST.get('imgdata').file.read()
    image.put()

Rather than using a uid property, think about using key_names for that purpose, and take a look at the get_or_insert method

Upvotes: 3

Related Questions