I noticed a few other posts in the archives asking for experience with the App Engine blobstore but there were no responses. Does anyone have any advice or tricks they'd like to share before I start figuring this out that pertain to Flask? Thanks, Dan
Hi Dan,
I went through the process of uploading mainly as an exercise for
my knowledge. I'll post my code here for information purposes, but its
not thoroughly tested and probably is not the best handler for it
however it works well for me. Oh and apart from the blobstore and cgi
(used to parse the header only) modules its pure Flask which I like.
This is the code that returns the upload template, a simple form that
posts to upload_url
@app.route('/upload/', methods=['GET','POST'])
@login_required
def uploads():
upload_url =
blobstore.create_upload_url(url_for('uploads_handler'))
if request.is_xhr:
return upload_url
else:
return render_template('upload.html', upload_url=upload_url)
Heres the form:
<form method="post" action="{{ upload_url }}" enctype="multipart/form-
data">
<dl>
<input type="file" name="file" />
<input type="hidden" name="item" value="{{ item.key() }}" />
<input type="hidden" name="return"
value="{{ request.base_url }}" />
</dl>
<input type="submit" name="button" class="btn" value="Upload" />
</form>
This is the handler that the blobstore redirects to after storing the
blob. Essentially this code gets the blobkey from the header,
retrieves the blob information from th blobstore, writes that to my
table and then performs a redirect to the final page. There were a
couple of traps for young players here. First getting the blob_key
from the file uploads header took me some time, but with some help
from this list I worked through it. Second was the blobstore requires
the handler to return a redirect with no data, so I had to modify the
standard redirect response as you will see.
@app.route('/upload/handler/', methods=['GET','POST'])
@login_required
def uploads_handler():
#key is stored in the header for each file uploaded
type, params =
cgi.parse_header(request.files['file'].headers['Content-Type'])
blob_key = blobstore.BlobKey(params['blob-key'])
blob = blobstore.BlobInfo.get(blob_key)
item = Page_Items.get(request.values['item'])
upload = Uploads(owner = g.user.owner,
filename = blob.filename,
mime_type = blob.content_type,
blob = blob,
items = [item.key()])
if blob.content_type in app.config['IMAGE_TYPES']:
upload.download_url = images.get_serving_url(str(blob_key))
upload.put()
if item.images:
item_imgs = json.loads(item.images)
else:
item_imgs = []
item_imgs.append({'key': str(upload.key()), 'url' :
upload.download_url, 'filename' : upload.filename })
item.images = json.dumps(item_imgs)
item.put()
response = redirect(request.values['return'])
response.data = ''
return response
Hope it helps
Adam
On Jan 7, 2011, at 9:15 PM, Dan Ross wrote:
> I noticed a few other posts in the archives asking for experience
> with the App Engine blobstore but there were no responses.
>
> Does anyone have any advice or tricks they'd like to share before I
> start figuring this out that pertain to Flask?
>
> Thanks,
>
> Dan
Spectacular. That gives me some reference to work with. Thanks Adam. On Jan 7, 2011, at 10:13 PM, Adam Oakman wrote: > Hi Dan, > I went through the process of uploading mainly as an exercise for > my knowledge. I'll post my code here for information purposes, but its > not thoroughly tested and probably is not the best handler for it > however it works well for me. Oh and apart from the blobstore and cgi > (used to parse the header only) modules its pure Flask which I like. > > > This is the code that returns the upload template, a simple form that > posts to upload_url > > @app.route('/upload/', methods=['GET','POST']) > @login_required > def uploads(): > upload_url = > blobstore.create_upload_url(url_for('uploads_handler')) > if request.is_xhr: > return upload_url > else: > return render_template('upload.html', upload_url=upload_url) > > Heres the form: > > <form method="post" action="{{ upload_url }}" enctype="multipart/form- > data"> > <dl> > <input type="file" name="file" /> > <input type="hidden" name="item" value="{{ item.key() }}" /> > <input type="hidden" name="return" > value="{{ request.base_url }}" /> > </dl> > <input type="submit" name="button" class="btn" value="Upload" /> > </form> > > This is the handler that the blobstore redirects to after storing the > blob. Essentially this code gets the blobkey from the header, > retrieves the blob information from th blobstore, writes that to my > table and then performs a redirect to the final page. There were a > couple of traps for young players here. First getting the blob_key > from the file uploads header took me some time, but with some help > from this list I worked through it. Second was the blobstore requires > the handler to return a redirect with no data, so I had to modify the > standard redirect response as you will see. > > @app.route('/upload/handler/', methods=['GET','POST']) > @login_required > def uploads_handler(): > #key is stored in the header for each file uploaded > type, params = > cgi.parse_header(request.files['file'].headers['Content-Type']) > blob_key = blobstore.BlobKey(params['blob-key']) > blob = blobstore.BlobInfo.get(blob_key) > item = Page_Items.get(request.values['item']) > upload = Uploads(owner = g.user.owner, > filename = blob.filename, > mime_type = blob.content_type, > blob = blob, > items = [item.key()]) > if blob.content_type in app.config['IMAGE_TYPES']: > upload.download_url = images.get_serving_url(str(blob_key)) > upload.put() > if item.images: > item_imgs = json.loads(item.images) > else: > item_imgs = [] > item_imgs.append({'key': str(upload.key()), 'url' : > upload.download_url, 'filename' : upload.filename }) > item.images = json.dumps(item_imgs) > item.put() > response = redirect(request.values['return']) > response.data = '' > return response > > Hope it helps > > Adam > > On Jan 7, 2011, at 9:15 PM, Dan Ross wrote: > >> I noticed a few other posts in the archives asking for experience >> with the App Engine blobstore but there were no responses. >> >> Does anyone have any advice or tricks they'd like to share before I >> start figuring this out that pertain to Flask? >> >> Thanks, >> >> Dan >
You can also use werkzeug's own parse_options_header to parse out the blob key:
Something like this:
from flask import request
from werkzeug import parse_options_header
def get_blob_key(field_name, blob_key=None):
"""Parse out and return the blob key from a file uploaded via the App Engine
Blobstore API.
"""
try:
upload_file = request.files[field_name]
header = upload_file.headers['Content-Type']
parsed_header = parse_options_header(header)
blob_key = parsed_header[1]['blob-key']
except:
# something went wrong
return blob_key
This obviously only deals with one uploaded file in one form field,
but it illustrates the usage reasonably.
Once you've got the elusive blob key parsed out of the Content-Type
header, you're good to go.
Paul
On 8 January 2011 06:17, Dan Ross <dan@rosspixelworks.com> wrote:
> Spectacular. That gives me some reference to work with. Thanks Adam.
>
> On Jan 7, 2011, at 10:13 PM, Adam Oakman wrote:
>
>> Hi Dan,
>> I went through the process of uploading mainly as an exercise for
>> my knowledge. I'll post my code here for information purposes, but its
>> not thoroughly tested and probably is not the best handler for it
>> however it works well for me. Oh and apart from the blobstore and cgi
>> (used to parse the header only) modules its pure Flask which I like.
>>
>>
>> This is the code that returns the upload template, a simple form that
>> posts to upload_url
>>
>> @app.route('/upload/', methods=['GET','POST'])
>> @login_required
>> def uploads():
>> upload_url =
>> blobstore.create_upload_url(url_for('uploads_handler'))
>> if request.is_xhr:
>> return upload_url
>> else:
>> return render_template('upload.html', upload_url=upload_url)
>>
>> Heres the form:
>>
>> <form method="post" action="{{ upload_url }}" enctype="multipart/form-
>> data">
>> <dl>
>> <input type="file" name="file" />
>> <input type="hidden" name="item" value="{{ item.key() }}" />
>> <input type="hidden" name="return"
>> value="{{ request.base_url }}" />
>> </dl>
>> <input type="submit" name="button" class="btn" value="Upload" />
>> </form>
>>
>> This is the handler that the blobstore redirects to after storing the
>> blob. Essentially this code gets the blobkey from the header,
>> retrieves the blob information from th blobstore, writes that to my
>> table and then performs a redirect to the final page. There were a
>> couple of traps for young players here. First getting the blob_key
>> from the file uploads header took me some time, but with some help
>> from this list I worked through it. Second was the blobstore requires
>> the handler to return a redirect with no data, so I had to modify the
>> standard redirect response as you will see.
>>
>> @app.route('/upload/handler/', methods=['GET','POST'])
>> @login_required
>> def uploads_handler():
>> #key is stored in the header for each file uploaded
>> type, params =
>> cgi.parse_header(request.files['file'].headers['Content-Type'])
>> blob_key = blobstore.BlobKey(params['blob-key'])
>> blob = blobstore.BlobInfo.get(blob_key)
>> item = Page_Items.get(request.values['item'])
>> upload = Uploads(owner = g.user.owner,
>> filename = blob.filename,
>> mime_type = blob.content_type,
>> blob = blob,
>> items = [item.key()])
>> if blob.content_type in app.config['IMAGE_TYPES']:
>> upload.download_url = images.get_serving_url(str(blob_key))
>> upload.put()
>> if item.images:
>> item_imgs = json.loads(item.images)
>> else:
>> item_imgs = []
>> item_imgs.append({'key': str(upload.key()), 'url' :
>> upload.download_url, 'filename' : upload.filename })
>> item.images = json.dumps(item_imgs)
>> item.put()
>> response = redirect(request.values['return'])
>> response.data = ''
>> return response
>>
>> Hope it helps
>>
>> Adam
>>
>> On Jan 7, 2011, at 9:15 PM, Dan Ross wrote:
>>
>>> I noticed a few other posts in the archives asking for experience
>>> with the App Engine blobstore but there were no responses.
>>>
>>> Does anyone have any advice or tricks they'd like to share before I
>>> start figuring this out that pertain to Flask?
>>>
>>> Thanks,
>>>
>>> Dan
>>
>
>
Dan, it also bears repeating here that you *must* enable Billing in your application before trying to use the Blobstore API in the production environment. Just mentioning that because it burned me! Paul On 8 January 2011 09:56, Paul Burt <paul.burt@gmail.com> wrote: > You can also use werkzeug's own parse_options_header to parse out the blob key: > > Something like this: > > from flask import request > from werkzeug import parse_options_header > > def get_blob_key(field_name, blob_key=None): > """Parse out and return the blob key from a file uploaded via the App Engine > Blobstore API. > > """ > try: > upload_file = request.files[field_name] > header = upload_file.headers['Content-Type'] > parsed_header = parse_options_header(header) > blob_key = parsed_header[1]['blob-key'] > except: > # something went wrong > return blob_key > > This obviously only deals with one uploaded file in one form field, > but it illustrates the usage reasonably. > > Once you've got the elusive blob key parsed out of the Content-Type > header, you're good to go. > > Paul > > > On 8 January 2011 06:17, Dan Ross <dan@rosspixelworks.com> wrote: >> Spectacular. That gives me some reference to work with. Thanks Adam. >> >> On Jan 7, 2011, at 10:13 PM, Adam Oakman wrote: >> >>> Hi Dan, >>> I went through the process of uploading mainly as an exercise for >>> my knowledge. I'll post my code here for information purposes, but its >>> not thoroughly tested and probably is not the best handler for it >>> however it works well for me. Oh and apart from the blobstore and cgi >>> (used to parse the header only) modules its pure Flask which I like. >>> >>> >>> This is the code that returns the upload template, a simple form that >>> posts to upload_url >>> >>> @app.route('/upload/', methods=['GET','POST']) >>> @login_required >>> def uploads(): >>> upload_url = >>> blobstore.create_upload_url(url_for('uploads_handler')) >>> if request.is_xhr: >>> return upload_url >>> else: >>> return render_template('upload.html', upload_url=upload_url) >>> >>> Heres the form: >>> >>> <form method="post" action="{{ upload_url }}" enctype="multipart/form- >>> data"> >>> <dl> >>> <input type="file" name="file" /> >>> <input type="hidden" name="item" value="{{ item.key() }}" /> >>> <input type="hidden" name="return" >>> value="{{ request.base_url }}" /> >>> </dl> >>> <input type="submit" name="button" class="btn" value="Upload" /> >>> </form> >>> >>> This is the handler that the blobstore redirects to after storing the >>> blob. Essentially this code gets the blobkey from the header, >>> retrieves the blob information from th blobstore, writes that to my >>> table and then performs a redirect to the final page. There were a >>> couple of traps for young players here. First getting the blob_key >>> from the file uploads header took me some time, but with some help >>> from this list I worked through it. Second was the blobstore requires >>> the handler to return a redirect with no data, so I had to modify the >>> standard redirect response as you will see. >>> >>> @app.route('/upload/handler/', methods=['GET','POST']) >>> @login_required >>> def uploads_handler(): >>> #key is stored in the header for each file uploaded >>> type, params = >>> cgi.parse_header(request.files['file'].headers['Content-Type']) >>> blob_key = blobstore.BlobKey(params['blob-key']) >>> blob = blobstore.BlobInfo.get(blob_key) >>> item = Page_Items.get(request.values['item']) >>> upload = Uploads(owner = g.user.owner, >>> filename = blob.filename, >>> mime_type = blob.content_type, >>> blob = blob, >>> items = [item.key()]) >>> if blob.content_type in app.config['IMAGE_TYPES']: >>> upload.download_url = images.get_serving_url(str(blob_key)) >>> upload.put() >>> if item.images: >>> item_imgs = json.loads(item.images) >>> else: >>> item_imgs = [] >>> item_imgs.append({'key': str(upload.key()), 'url' : >>> upload.download_url, 'filename' : upload.filename }) >>> item.images = json.dumps(item_imgs) >>> item.put() >>> response = redirect(request.values['return']) >>> response.data = '' >>> return response >>> >>> Hope it helps >>> >>> Adam >>> >>> On Jan 7, 2011, at 9:15 PM, Dan Ross wrote: >>> >>>> I noticed a few other posts in the archives asking for experience >>>> with the App Engine blobstore but there were no responses. >>>> >>>> Does anyone have any advice or tricks they'd like to share before I >>>> start figuring this out that pertain to Flask? >>>> >>>> Thanks, >>>> >>>> Dan >>> >> >> >
I saw that as well. That's why I'm trying to gather as much info as possible so I don't accidentally cost myself a bunch of money. Thanks Paul. On Jan 8, 2011, at 4:16 AM, Paul Burt wrote: > Dan, it also bears repeating here that you *must* enable Billing in > your application before trying to use the Blobstore API in the > production environment. > > Just mentioning that because it burned me! > > Paul > > > On 8 January 2011 09:56, Paul Burt <paul.burt@gmail.com> wrote: >> You can also use werkzeug's own parse_options_header to parse out the blob key: >> >> Something like this: >> >> from flask import request >> from werkzeug import parse_options_header >> >> def get_blob_key(field_name, blob_key=None): >> """Parse out and return the blob key from a file uploaded via the App Engine >> Blobstore API. >> >> """ >> try: >> upload_file = request.files[field_name] >> header = upload_file.headers['Content-Type'] >> parsed_header = parse_options_header(header) >> blob_key = parsed_header[1]['blob-key'] >> except: >> # something went wrong >> return blob_key >> >> This obviously only deals with one uploaded file in one form field, >> but it illustrates the usage reasonably. >> >> Once you've got the elusive blob key parsed out of the Content-Type >> header, you're good to go. >> >> Paul >> >> >> On 8 January 2011 06:17, Dan Ross <dan@rosspixelworks.com> wrote: >>> Spectacular. That gives me some reference to work with. Thanks Adam. >>> >>> On Jan 7, 2011, at 10:13 PM, Adam Oakman wrote: >>> >>>> Hi Dan, >>>> I went through the process of uploading mainly as an exercise for >>>> my knowledge. I'll post my code here for information purposes, but its >>>> not thoroughly tested and probably is not the best handler for it >>>> however it works well for me. Oh and apart from the blobstore and cgi >>>> (used to parse the header only) modules its pure Flask which I like. >>>> >>>> >>>> This is the code that returns the upload template, a simple form that >>>> posts to upload_url >>>> >>>> @app.route('/upload/', methods=['GET','POST']) >>>> @login_required >>>> def uploads(): >>>> upload_url = >>>> blobstore.create_upload_url(url_for('uploads_handler')) >>>> if request.is_xhr: >>>> return upload_url >>>> else: >>>> return render_template('upload.html', upload_url=upload_url) >>>> >>>> Heres the form: >>>> >>>> <form method="post" action="{{ upload_url }}" enctype="multipart/form- >>>> data"> >>>> <dl> >>>> <input type="file" name="file" /> >>>> <input type="hidden" name="item" value="{{ item.key() }}" /> >>>> <input type="hidden" name="return" >>>> value="{{ request.base_url }}" /> >>>> </dl> >>>> <input type="submit" name="button" class="btn" value="Upload" /> >>>> </form> >>>> >>>> This is the handler that the blobstore redirects to after storing the >>>> blob. Essentially this code gets the blobkey from the header, >>>> retrieves the blob information from th blobstore, writes that to my >>>> table and then performs a redirect to the final page. There were a >>>> couple of traps for young players here. First getting the blob_key >>>> from the file uploads header took me some time, but with some help >>>> from this list I worked through it. Second was the blobstore requires >>>> the handler to return a redirect with no data, so I had to modify the >>>> standard redirect response as you will see. >>>> >>>> @app.route('/upload/handler/', methods=['GET','POST']) >>>> @login_required >>>> def uploads_handler(): >>>> #key is stored in the header for each file uploaded >>>> type, params = >>>> cgi.parse_header(request.files['file'].headers['Content-Type']) >>>> blob_key = blobstore.BlobKey(params['blob-key']) >>>> blob = blobstore.BlobInfo.get(blob_key) >>>> item = Page_Items.get(request.values['item']) >>>> upload = Uploads(owner = g.user.owner, >>>> filename = blob.filename, >>>> mime_type = blob.content_type, >>>> blob = blob, >>>> items = [item.key()]) >>>> if blob.content_type in app.config['IMAGE_TYPES']: >>>> upload.download_url = images.get_serving_url(str(blob_key)) >>>> upload.put() >>>> if item.images: >>>> item_imgs = json.loads(item.images) >>>> else: >>>> item_imgs = [] >>>> item_imgs.append({'key': str(upload.key()), 'url' : >>>> upload.download_url, 'filename' : upload.filename }) >>>> item.images = json.dumps(item_imgs) >>>> item.put() >>>> response = redirect(request.values['return']) >>>> response.data = '' >>>> return response >>>> >>>> Hope it helps >>>> >>>> Adam >>>> >>>> On Jan 7, 2011, at 9:15 PM, Dan Ross wrote: >>>> >>>>> I noticed a few other posts in the archives asking for experience >>>>> with the App Engine blobstore but there were no responses. >>>>> >>>>> Does anyone have any advice or tricks they'd like to share before I >>>>> start figuring this out that pertain to Flask? >>>>> >>>>> Thanks, >>>>> >>>>> Dan >>>> >>> >>> >>