I am using the App Engine python development server 1.9.20 on a Mac.
I've had success with the Blobstore but I'm switching my code to use cloudstore before I launch my site.
I'm not getting any errors in the console. But I'm not getting an image displayed in the browser. The browser displays the "image not found icon". ("?" in Safari.)
I cobbled together my cloud storage code from examples referenced here on SO.
Mostly from voscausa's code (ref below).
The serving url looks correct (based what I would expect from the sample documentation).
But no image. If you have any idea what I'm doing wrong, I would be pleased to hear your input.
I'm saving the uploaded image blob key and url to the UserProfile entity.
class UserProfile(ndb.Model):
profile_image_url = ndb.StringProperty(indexed=False, default=None)
profile_image_key = ndb.BlobKeyProperty(indexed=False, default=None)
I write to the GCS and generate a blobstore key here:
def CreateFile(filename, upload_file, content_type):
with gcs.open(filename, 'w',
options={b'x-goog-acl': b'public-read'},
content_type=content_type) as f:
f.write(upload_file)
blobstore_filename = '/gs' + filename
return blobstore.create_gs_key(blobstore_filename)
My upload handler looks like this:
class UploadHandler(webapp2.RequestHandler):
def post(self):
user = users.get_current_user()
path = self.request.path
item = self.request.get('item')
image_num = self.request.get('image')
src = self.request.get('src')
group_id = self.request.get('id')
if user:
this_user_qry = UserProfile.query(UserProfile.user_id == user.user_id(), ancestor=user_key(user.user_id()))
try:
this_user = this_user_qry.get()
except:
logging.error('In UploadHandler, src = profile this_user_qry.get() failed')
if src == 'profile':
return_path = '/edit_profile#image'
#if this_user.profile_image_key != None:
#''' profile image exists, removing the current image, replaced with this_user.profile_image_key '''
#blobstore.delete(this_user.profile_image_key)
#this_user.profile_image_key = None
#this_user.profile_image_url = None
bucket_name = os.environ.get('BUCKET_NAME',
app_identity.get_default_gcs_bucket_name())
file_data = self.request.get("file", default_value=None)
file_name = self.request.POST["file"].filename
file_ext = file_name.lower().split('.')[-1]
gcs_file = "/%s/profile/%s/%s" % (bucket_name, str(user.user_id()), file_name)
#gcs_file = "/%s/%s" % (bucket_name, file_name)
mimetypes.init()
content_type = mimetypes.guess_type(file_name)[0]
if file_data:
blob_key = blobstore.BlobKey(CreateFile(gcs_file, file_data, content_type))
if file_ext in ['png', 'jpg', 'gif']:
serving_url = images.get_serving_url(
blobstore.create_gs_key('/gs' + gcs_file), secure_url=True)
elif gae_development:
# this SDK feature has not been documented yet !!!
serving_url = 'http://localhost:8080/_ah/gcs' + gcs_file
else:
serving_url = 'https://storage.googleapis.com' + gcs_file
print "\n-new-\nserving_url = %s" % serving_url
this_user.profile_image_key = blob_key
this_user.profile_image_url = serving_url
try:
this_user.put()
except:
logging.exception('In UploadHandler, if blob_key, this_user.put()')
self.redirect('/upload_image_error')
else:
self.redirect('/edit_profile#image')
The printed values for [gcs_file, blob_key, serving_url] are:
gcs_file = /app_default_bucket/profile/112118202356943244222/MichaelEdland_112514.jpg
blob_key = encoded_gs_file:YXBwX2RlZmF1bHRfYnVja2V0L3Byb2ZpbGUvMTEyMTE4MjAyMzU2OTQzMjQ0MjIyL01pY2hhZWxFZGxhbmRfMTEyNTE0LmpwZw==
serving_url = http://0.0.0.0:8080/_ah/img/encoded_gs_file:YXBwX2RlZmF1bHRfYnVja2V0L3Byb2ZpbGUvMTEyMTE4MjAyMzU2OTQzMjQ0MjIyL01pY2hhZWxFZGxhbmRfMTEyNTE0LmpwZw==
For the Jinja template:
I'm passing this value to the template:
'profile_image_url': this_user.profile_image_url,
And this to display the image on the profile page:
<img border="0" src="{{ profile_image_url | safe }}" width="100%" >
In the App Engine Console Datastore Viewer
Entity Kind Blobinfo has two entries for this one image
Key Names
1) 3kD4IorO9hfg-J7OrZtmVQ==
2) encoded_gs_file:YXBwX2RlZmF1bHRfYnVja2V0L3Byb2ZpbGUvMTEyMTE4MjAyMzU2OTQzMjQ0MjIyL01pY2hhZWxFZGxhbmRfMTEyNTE0LmpwZw==
filenames
1) MichaelEdland_112514.jpg
2) None
sizes
1) 166464
2) 250
There's one entry for BlobServingUrl
key name and blob_key are both:
encoded_gs_file:YXBwX2RlZmF1bHRfYnVja2V0L3Byb2ZpbGUvMTEyMTE4MjAyMzU2OTQzMjQ0MjIyL01pY2hhZWxFZGxhbmRfMTEyNTE0LmpwZw==
GSFileInfo
Key Name =
encoded_gs_file:YXBwX2RlZmF1bHRfYnVja2V0L3Byb2ZpbGUvMTEyMTE4MjAyMzU2OTQzMjQ0MjIyL01pY2hhZWxFZGxhbmRfMTEyNTE0LmpwZw==
content_type = image/jpeg
filename = /app_default_bucket/profile/112118202356943244222/MichaelEdland_112514.jpg
Some things I found helpful (to get to this point):
voscausa's answer was helpful How to serve cloudstorage files using app engine SDK
and his revised code example was helpful https://github.com/voscausa/appengine-gcs-blobstore-python
in the documentation there is an example of what the serving url looks like
I did also read the Google docs, which got me this far. (I can't post the links because of a lack of reputation)
But now I appear to be stuck.
Thanks in advance. After a year of using StackOverflow every day, I finally have to ask a question. :-) Probably 511 (too much information) but I appreciate the help.