Tutorial :Base64 encode binary uploaded data on the AppEngine


I've been trying to Base64 encode image data from the user (in this case a trusted admin) in order to skip as many calls to the BlobStore as I possibly can. Every time I attempt to encode it, I recieve an error saying:

Error uploading image: 'ascii' codec can't decode byte 0x89 in position 0: ordinal not in range(128)  

I've googled the error (the less significant parts) and found that it may have something to do with Unicode (?). The template portion is just a basic upload form, while the handler contains the following code:

  def post(self,id):      logging.info("ImagestoreHandler#post %s", self.request.path)      fileupload = self.request.POST.get("file",None)      if fileupload is None : return self.error(400)        content_type = fileupload.type or getContentType( fileupload.filename )      if content_type is None:         self.error(400)        self.response.headers['Content-Type'] = 'text/plain'        self.response.out.write( "Unsupported image type: " + fileupload.filename )        return      logging.debug( "File upload: %s, mime type: %s", fileupload.filename, content_type )        try:        (img_name, img_url) = self._store_image(          fileupload.filename, fileupload.file, content_type )        self.response.headers['Location'] = img_url        ex=None      except Exception, err:        logging.exception( "Error while storing image" )        self.error(400)        self.response.headers['Content-Type'] = 'text/plain'        self.response.out.write("Error uploading image: " + str(err))        return      #self.redirect(urlBase % img.key() )  #dummy redirect is acceptable for non-AJAX clients,      # location header should be acceptable for true REST clients, however AJAX requests       # might not be able to access the location header so we'll write a 200 response with       # the new URL in the response body:        acceptType = self.request.accept.best_match( listRenderers.keys() )      out = self.response.out      if acceptType == 'application/json':        self.response.headers['Content-Type'] = 'application/json'        out.write( '{"name":"%s","href":"%s"}' % ( img_name, img_url ) )      elif re.search( 'html|xml', acceptType ):        self.response.headers['Content-Type'] = 'text/html'        out.write( '<a href="%s">%s</a>' % ( img_url, img_name) )      def _store_image(self, name, file, content_type):      """POST handler delegates to this method for actual image storage; as      a result, alternate implementation may easily override the storage      mechanism without rewriting the same content-type handling.         This method returns a tuple of file name and image URL."""        img_enc = base64.b64encode(file.read())      img_enc_struct = "data:%s;base64,%s" % (content_type, img_enc)        img = Image( name=name, data=img_enc_struct )      img.put()      logging.info("Saved image to key %s", img.key() )       return ( str(img.name), img.key() )  

My image model:

from google.appengine.ext import db    class Image(db.Model):      name = db.StringProperty(required=True)    data = db.TextProperty(required=True)    created = db.DateTimeProperty(auto_now_add=True)    owner = db.UserProperty(auto_current_user_add=True)  

Any help is greatly appreciated. This code, minus my image encoding in _store_image, comes from the blooger branch of gvdent here.


your store image code could be like this....

img = Image( name=name, data=file.read() )  img.put()  return ( str(img.name), img.key() )  

doing base64encode of binary data may increase the size of data itself and increase the cpu encoding and decoding time.

and Blobstore uses the same storage sturcuture as datastore, so it is just making easier to use file upload store download.

Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Next Post »