I would like to add a feature to my GAE app that basically delivers avatar-like images for resources stored in the app's HRD datastore (NDB API), i.e. 1 image per entity. In most cases, the app would only serve small thumbnails of these images (100 x 100px, ~15kB). Typically, there are 10 to 40 thumbnails per page. In rare cases (less than 5%) a page includes a request for the larger version of a single image (200 x 200px).
The most important requirement would be, that I can use a user-defined (SSL) URL per image, served from the same custom domain as my app. Images are rarely changed, but if so the URL must not change.
URL pattern: https://www.mydomain.com/img/uniqueKey?s=100
Where the s
parameter would tell which size and where uniqueKey represents the URL-encoded NDB key of the entity that is represented by the image. Hence, it is a 1-to-1 relationship between entity and image. BTW, it doesn't matter that the NDB key is exposed.
Alternatively, I think it would be acceptable to have a different subdomain just for these images, e.g.: https://img.mydomain.com/uniqueKey?s=100
The other requirement would be that serving these images is under access control (custom authentication based on webapp2), not oAuth or Google accounts respectively. As far as I understand, this would mean that I have to implement specific handlers that will consume frontend instance hours whenever GET requests for these images are processed, just the same as with my entities in the datastore.
The options I see:
An image
BlobProperty that I store with each entity, maybe two, one for each size. The ImageHandler would only get that single blob per request, so it would be a small op.
As far as I understand, I can implement the image handler with custom authentication / access control. But how do I use custom, predefined URLs that won't change even when the image is modified. The generated URLs look random to me and from a different domain.
As far as I understand, I can predefine the URLs and also can update images in the background. But I think these are all public URLs with oAuth2 based access control, and again not custom domain.
It seems that BlobProperty might be more expensive and less convenient for serving files, but it is the only approach that meets all the requirements. Or did I miss something here and I could go with BlobStore or GCS?
You can do it with any of these options. Cloud Storage because it is the cheapest, BlobStore or Blob properties are easier.
You create a servlet to process requests with /image in them. This servlet uses an image id that you provided in the request, looks up a Cloud Storage key associated with this id, retrieves the file from Cloud Storage, and returns it in response. You can add some authentication logic, if necessary. You will need an entity to store "id - GCS key" pairs. Bandwidth between GCS and App Engine is free.
If you go with BlobStore or Datastore, you avoid an extra trip to Cloud Storage. With a BlobStore you still need an entity to associate image ids with BlobStore keys.
You can also store images in Memcache with their ids as keys. This way you avoid a trip to the Cloud Storage or BlobStore/Datastore.