I am building an app-engine endpoint api that takes picture from a user (android app) and saves it to blobstore programmatically. Then I save the blob_key in my datastore. The code goes like this:
First I received the image through my
@endpoint.method
as amessages.BytesField
:image_data = messages.BytesField(1, required=True)
Then I save to the blobstore like this:
from google.appengine.api import files
def save_image(data):
# Create the file
file_name = files.blobstore.create(mime_type='image/png')
# Open the file and write to it
with files.open(file_name, 'a') as f:
f.write('data')
# Finalize the file. Do this before attempting to read it.
files.finalize(file_name)
# Get the file's blob key
blob_key = files.blobstore.get_blob_key(file_name)
return blob_key # which is then saved to datastore
Now I want to serve the image back. I don't see how to fit the following code into my endpoints api:
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)
In the end I imagine a serving procedure like this:
in @endpoints.method:
get blob_key from datastore
obtain image with blob_key
add image to StuffResponseMessage
send StuffResponseMessage to front-end (android app)
My approach is because I want to protect the privacy of my users. Any thoughts on how to do this well? My code snippets are generally from the google developer tutorial.
EDIT:
I don't see how I would pass the blob_key from the datastore to the following method to retrieve the image:
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)
What's inside resource
, anyway?
I believe
resource
is theBlobKey
object of what you want to serve, as a string, retreived from url path. If you look at the source ofgoogle.appengine.ext.blobstore.BlobInfo
theget
method uses a function__normalize_and_convert_keys
that takes an argument ofBlobKey
object OR string.If the blob is an image, maybe it's best to send the serving url instead to your Android app, in
StuffResponseMessage
maybe in your case. From google's Serving a Blob doc:So after you save the image, take the returned
blob_key
(as per your methodsave_image(data)
above) to make a serving url, then in your Android app get the image from the returned url. That of course means exposing the image url without privacy protection.If you want to do it with protection, use
BlobReader
class to read the blob with file like interface. You can't use the method/class from Serving a Blob example because you do it in aremote.Service
subclass rather than a handler.