my blobstore_image model:
db.define_table('blobstore_image',
db.version_info,
Field('blob_key', 'upload', notnull=True,
requires=IS_LENGTH(1048576),
represent=lambda image : A('download', _href=URL(
r=request, c='gae_blobstore', f='download',
args=[image])),
label="Image"),
Field('image_url', length=500),
Field('name', length=128,
requires=IS_NOT_IN_DB(db, 'blobstore_image.name')),
Field('type', length=128, requires=IS_IN_SET(['i_classify',
'my_images',
'by_type'],
zero=None)),
migrate=True)
my upload controller:
def upload_image():
"""
This is the integration of the GAE blobstore with the image upload process
@TODO: figure out how to test this. image upload is going to be kinda
difficult to spoof
"""
#@TODO: how do we deal with deleting an image?
logging.info(repr(request.post_vars))
fields=['name',
'type',
'blob_key']
form = SQLFORM(db.blobstore_image, fields=fields,
formstyle='divs')
if request.args and request.args[0]:
form = SQLFORM(db.blobstore_image, request.args[0], fields=fields,
upload=URL(r=request, c='gae_blobstore', f='preview'),
formstyle='divs')
if request.env.web2py_runtime_gae:
from google.appengine.ext import blobstore
from google.appengine.api.images import get_serving_url
import uuid
#get the blob_info. NOTE this MUST be done before any other operations
on
# the request vars. otherwise something modifies them (perhaps the form
# validators) in a way that makes this not work
blob_info = None
if request.vars.blob_key == '':
#it seems that prod blobstore returns empty string instead of None
when
#there are no changes to the image
request.vars.blob_key = None
if request.vars.blob_key != None:
blob_info = blobstore.parse_blob_info(request.vars.blob_key)
del request.vars['blob_key']
upload_url = blobstore.create_upload_url(URL(r=request,f='upload_image',
args=request.args,
vars={'redir':URL(r=request,c='dataadmin', f='index')}))
form['_action']=upload_url
#since we are setting the action after the form was initially created we
# need to reset the form.custom.begin
(begin, end) = form._xml()
form.custom.begin = XML("<%s %s>" % (form.tag, begin))
if form.accepts(request.vars,session, formname="uploadimage"):
#@TODO: can this be a post-validation function?
#get the record we just inserted/modified
row = db(db.blobstore_image.id == form.vars.id).select().first()
if request.vars.blob_key__delete == 'on' or \
(blob_info and (row and row.blob_key)):
#remove from blobstore because of delete or update of image
decoded_key = base64.b64decode(row.blob_key.split('.')[0])
blobstore.delete(decoded_key)
#remove reference in the artwork record
row.update_record(blob_key=None)
if blob_info:
logging.info("adding blob_key " + str(blob_info.key()))
#add reference to image in this record
key = base64.b64encode(str(blob_info.key())) +"." +
blob_info.content_type.split('/')[1]
url = get_serving_url(str(blob_info.key()))
row.update_record(blob_key = key, image_url = url)
crud.archive(form)
session.flash="Image saved"
#Raise the HTTP exception so that the response content stays empty.
#calling redirect puts content in the body which fails the blob
upload
raise HTTP(303,
Location= URL(r=request,f='upload_image',
args=form.vars.id))
elif form.errors:
#logging.info("form not accepted")
logging.info(form.errors)
session.flash=BEAUTIFY(form.errors)
#there was an error, let's delete the newly uploaded image
if blob_info:
blobstore.delete(blob_info.key())
#Raise the HTTP exception so that the response content stays empty.
#calling redirect puts content in the body which fails the blob
upload
redirvars = {}
redirvars['form_errors']=True
redirvars['error_dict'] = form.errors
raise HTTP(303,
Location= URL(r=request,f='upload_image',
args=request.args,
vars=redirvars))
return dict(form=form,
aahome=A("data Home", _href=URL(r=request, f='index')),
back=A("Query view",
_href=URL(r=request, f='query',
args=['blobstore_image'])))
hope that helps!
cfh