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 a messages.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 the BlobKey
object of what you want to serve, as a string, retreived from url path. If you look at the source of google.appengine.ext.blobstore.BlobInfo
the get
method uses a function __normalize_and_convert_keys
that takes an argument of BlobKey
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:
If you are serving images, a more efficient and potentially less-expensive method is to use get_serving_url using the App Engine Images API rather than send_blob. The get_serving_url function lets you serve the image directly, without having to go through your App Engine instances.
So after you save the image, take the returned blob_key
(as per your method save_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 a remote.Service
subclass rather than a handler.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With