Serve image from GAE datastore with Flask (python)
Asked Answered
T

2

6

I'd like to avoid using Webapp from GAE, so i use this code to upload an image to the Blobstore (code snippet from : http://flask.pocoo.org/mailinglist/archive/2011/1/8/app-engine-blobstore/#7fd7aa9a5c82a6d2bf78ccd25084ac3b)

@app.route("/upload", methods=['POST'])
def upload():
    if request.method == 'POST':
        f = request.files['file']
        header = f.headers['Content-Type']
        parsed_header = parse_options_header(header)
        blob_key = parsed_header[1]['blob-key']
        return blob_key

It returns what it seems to be indeed a Blobkey, wich is something like this :

2I9oX6J0U5nBCVw8kEndpw==

I then try to display the recently stored Blob image with this code :

@app.route("/testimgdisplay")
def test_img_display():
    response = make_response(db.get("2I9oX6J0U5nBCVw8kEndpw=="))
    response.headers['Content-Type'] = 'image/png'
    return response

Sadly this part doesn't work, I got the following error :

BadKeyError: Invalid string key 2I9oX6J0U5nBCVw8kEndpw==

Do you guys have faced this error before ? It seems the Blobkey is well-formatted, and I can't find a clue.

Telegraph answered 5/8, 2013 at 14:55 Comment(2)
I think the problem is that what you are getting as blobkey seems to be base64 encoded.Cons
Thx, it push me in the right direction ;)Telegraph
T
8

There was a simple mistake on the call for getting the Blob, I wrote:

db.get("2I9oX6J0U5nBCVw8kEndpw==")

and the right call was instead:

blobstore.get("2I9oX6J0U5nBCVw8kEndpw==")

For those looking for a complete Upload/Serving image via GAE Blobstore and Flask without using Webapp, here is the complete code:

Render the template for the upload form:

@app.route("/upload")
def upload():
    uploadUri = blobstore.create_upload_url('/submit')
    return render_template('upload.html', uploadUri=uploadUri)

Place your uploadUri in the form path (html):

<form action="{{ uploadUri }}" method="POST" enctype="multipart/form-data">

Here is the function to handle the upload of the image (I return the blob_key for practical reasons, replace it with your template):

@app.route("/submit", methods=['POST'])
def submit():
    if request.method == 'POST':
        f = request.files['file']
        header = f.headers['Content-Type']
        parsed_header = parse_options_header(header)
        blob_key = parsed_header[1]['blob-key']
        return blob_key

Now say you serve your images with a path like this:

/img/imagefilename

Then your image serving function is :

@app.route("/img/<bkey>")
def img(bkey):
    blob_info = blobstore.get(bkey)
    response = make_response(blob_info.open().read())
    response.headers['Content-Type'] = blob_info.content_type
    return response

Finally, anywhere you need to display an image in a template, you simply put the code:

<img src="/img/{{ bkey }} />
Telegraph answered 6/8, 2013 at 6:51 Comment(0)
B
0

I don't think Flask is any better or worse than Webapp in serving up Blobstore images, since they both use the Blobstore API for Serving a Blob.

What you're calling a Blobkey is just a string, which needs to be converted into a key (called resource here):

from google.appengine.ext import blobstore
from google.appengine.ext.webapp import blobstore_handlers
class ServeHandler(blobstore_handlers.BlobstoreDownloadHandler):
    def get(self, resource):
        resource = str(urllib.unquote(resource))
        blob_info = blobstore.BlobInfo.get(resource)
        self.send_blob(blob_info)
Bhutan answered 5/8, 2013 at 17:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.