Can I save images to Blobstore and save data to Datastore in one trip?
The argument has been made and settled on numerous occasions: Blobstore is better than DataStore for storing images. Now say I have an app similar to Instagram or Facebook or Yelp or any of those apps that are image intensive. In my particular case the ideal model would be
public class IdealPostModel{
Integer userId;
String synopsys;
Blob image;
...//more data/fields about the post
}
But since I must use the BlobStore, my model does not have a blob but instead a URL or BlobKey. The heavy catch is that to send a post (ie save a post to server) the app must -- in that order --
BlobstoreUtils.generateServingUrl(null)
data That's a lot of handshakes!!!
Is there a way to send all the data to the server in step one: strings and image. And then from there have the server do everything else? Of course I am here hoping to reduce the amount of work. I image App Engine must be quite mature by now and there has to be a simpler way than my architecture.
Now of course I am here because I am experiencing situations where the data is saved but the BlobKey or URL is not being saved to the Entity. It happens about 10% of the time. Or maybe less, but it does feel like 10%. It's driving my users insane, which means it's driving me even more insane since I don't want to lose my users.
Ideally
Update
public static String generateServingUrl(String path) {
BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();
return blobstoreService.createUploadUrl(null == path ? "/upload" : path);
}
This is a snippet on my server.
You actually cand send everything in a single request.
Bear in mind that when you send a blob using a URL gotten by calling blobstoreService.createUploadUrl("/yourservingurl") , GAE actually makes a first request to a different URL, stores the blob and then calls /yourservingurl passing you the blobkeys which you can retrive by doing:
Map<String, List<BlobKey>> blobs = blobstoreService.getUploads(req);
List<BlobKey> blobKeys = blobs.get("myFile");
So in effect all other form values will be lost after that first request, BUT if you can build that URL dynamically eg
blobstoreService.createUploadUrl("/yourservingurl?param1=a¶m2=b")
then you can get back those parameters on your Servlet and persist everything (including the blobkey of the already stored blob) at once, making much fewer calls to the datastore.
UPDATE: the steps would be
1) Gather all parameters on the client side and create an upload URL with those params eg: blobstoreService.createUploadUrl("/yourservingurl?userId=989787")
. GAE will generate a unique URL for that specific request.
when you commit the form, GAE will persist the blobs and call /yourservingurl
2) On the Servlet serving /yourservingurl you'll get all the blobkeys form files you uploaded by using : blobstoreService.getUploads(request)
AND you can get the parameters you included with the standard request.getParameter("userId")
3) Now in your servlet you have all the parameters (eg userId) you sent plus the blobkey, you can persist your Post object in one call.
The workflow is different. Given your example:
There is "Post" button and "Attach an image" button under a form for a new post.
When a user hits the Attach button, you ask a user to select a file and save it to the BlobStore (or Google Cloud Storage). There is no need to call BlobstoreUtils.generateServingUrl(null)
- you need to get an upload URL. When a call returns a key, you store it in the Post object.
When a user hits the Post button, you save the Post - including the image key (keys) in the Datastore. Thus, the entire workflow takes only two calls.
If a user hits the Cancel button - remember to delete the uploaded image(s) if any, or they will be orphaned. The tricky part is to delete these images if a user simply left your app or lost connection.
If you want, you can reverse the process - save post first, then let users attach images. This is not what most users expect, but it solves the problem with orphaned images.
链接地址: http://www.djcxy.com/p/67466.html上一篇: SQLite查询以不区分大小写的字母顺序