I am developing an app-engine connected android project using the eclipse plugin. When I upload an image to the blobstore, how do I make it callback an endpoint method? I find great posts here that can be used as reference to understand my question better (if you need to).
using blobstore with google cloud endpoint and android
Saving blobs with Google Endpoint
So really, I want to know how to make the callback url an endpoint method such as saveAnimalData below (I stole from referenced link)
#ApiMethod(name = "saveAnimalData", httpMethod = HttpMethod.POST)
public String saveAnimalData(AnimalData request) throws Exception {
}
You should be able to use
https://appid.appspot.com/_ah/api/apiname/version/saveAnimalData
As your final destination url when calling. blobstoreService.createUrl(destination) .
Just bear in mind that the request here is not your original submission. GAE will first call an internal URL (the one created by the blobstoreservice), store the blob and then call your destination URL so whatever info you send will be lost before reaching your endpoint (eg AnimalData will be null)
Related
how can I access a custom header from a server response when using TransferManager ?
we have a custom header added in the response from our server, from the client side we use multi part upload with default transfer manager
any suggestion how in how i could hook up it ?
so basically i want to pass over the response from the return response.getAwsResponse(); found in the class: AmazonS3Client on the method
private <X, Y extends AmazonWebServiceRequest> X invoke(Request<Y> request,
HttpResponseHandler<AmazonWebServiceResponse<X>> responseHandler,
String bucket, String key, boolean isAdditionalHeadRequestToFindRegion) {
that response will have the HTTP response from the server containing the custom heather which I'm after, basically is a unique Id send back when the file was 100% completed so than i can manipulate it.
I need to pass over this custom header from the response to the very beginning where I use the transfer manager and the upload.waitForCompletion(),
also i don't want to edit the amazon's,
so does anyone know if there is an interface or some other object which provides me access to it ?
After some debug into the framework I strongly believe that there is no way to have access to the http response when using the TransferManager
for what we are trying to do we need to send an unique id from the server to the client when the file upload is completed and assembled
** therefore if you don't mind in do not use the beauty of the TransferManager you could write "your own TransferMananger" than you will have full control, but again on the client side we don't really want to add custom code but have a standard and simple approach (but that is for my scenario), if you decide to do it manually it can be done I have already tried and works !
So as a alternative we though in send from the server via the eTag, which is not great but will do the job and will keep the client side simple and clean
Any suggestion in how to send this value back in a better way ?
Upload up = tm.upload(bucketName, file.getName(), file);
UploadResult result = (UploadResult) ((UploadImpl) up).getMonitor().getFuture().get();
String uniqueIdFromServer = result.getETag();
I am working on Google Sheets <-> Salesforce integration and developing it in Salesforce programming language - Apex on Force.com platform.
Currently I am attempting to connect to Google Sheets API. I am using Service Account Key, so Salesforce can pull the data from Google Sheets without the requirement for manual authorisation every time it sends out a query.
I am at the point where I set up the Service Account Key and I am successfully sending a request to it to obtain the access_code.
Then I am attempting to query the API, using the following class:
/****** API CALLOUT *******/
public static HttpResponse googleSheetsCallout (){
//the below line provides a string containing access token to google
string accessCode = getAccessToken();
//I found this endpoint structure online, this may be why my script
//isn't working. However, I am struggling to find the alternative.
string endpoint = 'https://sheets.googleapis.com/v4/spreadsheets/params=[SPREADSHEET ID GOES HERE]/values/[RANGE GOES HERE]?access_token=';
httpRequest req = new httpRequest();
req.setEndpoint(endpoint+accessCode);
req.setMethod('GET');
req.setTimeout(120000);
httpResponse res = new http().send(req);
System.debug ('res is ' +res);
return res;
}
When I run the function this is what the log returns:
|CALLOUT_RESPONSE|[71]|System.HttpResponse[Status=Forbidden, StatusCode=403]
|USER_DEBUG|[72]|DEBUG|res is System.HttpResponse[Status=Forbidden, StatusCode=403]
I enabled Google Sheets access in the google developer console menu, and what's interesting is when loking at the console it appears that Google notices API requests being sent out (they are appearing on the activity chart).
I solved it, and the issue was not the code itself.
The problem was sharing my sheet. To allow read/edit access to your sheet from the service account it must be shared with the Service Account ID email address, the same way it's shared with any other user. If this isn't done the script will produce 403 error.
I have an android app that wants to include image sending in the instant messaging client. I'm terribly confused on the way to do this using the blobstore or google cloud storage. Can someone please outline the steps to achieve this from the backend perspective? My goal is to end up using getServingUrl and have an external url for the app to hit and get the image. I'm using java and google cloud endpoints.
So far, I have:
1. createUploadUrl
2.user blogstore service .getUploads() to get BlobKeys
3.find my specific blob key (by ID, blobs.get(ID) i think)
4. magic
5. figure out how to use .getServingUrl(options) on a specific blob
6. backend works.
Please include code or psuedocode in your response, as I've been working on this for days and am beyond exhausted. I could really use someone to ELI5.
I think the confusing thing is trying to use it with cloud endpoints, which is not what you are supposed to do. Use a pure Servlets (or an abstraction over Servlet which gets you access to HttpServletRequest).
Get the BlobKey using BlobstoreService.getUpload(HttpServletRequest):
public void doGet(HttpServletRequest request, HttpServletResponse response) {
BlobKey blobKey = blobstoreService.getUploads(request).get("file").get(0); // assume the form parameter was "file" and only one file was uploaded
}
and use ImagesService.getServingUrl (set the BlobKey in the Options builder) to get the URL.
String url = imagesService.getServingUrl(ServingUrlOptions.Builder.withBlobKey(blobKey));
You may want to serialize the BlobKey (with getKeyString) to the datastore for future access.
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 (i.e. save a post to server) the app must -- in that order --
Send all the non-blob data to the server.
Wait for server to respond with BlobstoreUtils.generateServingUrl(null) data
Send the images to the BlobStore
Have BlobStore send response to my server with the BlobKey or url of the image
Store the BlobKey/url in my DataStore entity
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
App sends everything to server in one call: image and metadata such as userId and synopsys
Server somehow gets a blob key from Blobstore
Server sends image to blobstore, to be stored at the provided blob key, and server sends other data to DataStore, also including the blob key in the datastore.
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.
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.
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.
In a Google App Engine for Java web app, I am trying to use the low level api to invoke an XML RPC ...After looking at the docs, I figured out the following code to connect using low level API-the reason why I want to use Low Level API is so that I can set the timeout value myself--
String mrtime="120";
java.lang.Double maxresponsetime;
maxresponsetime = Double.valueOf(mrtime).doubleValue();
HTTPRequest req= new HTTPRequest(url, HTTPMethod.GET, disallowTruncate().setDeadline(maxresponsetime));
HTTPResponse response= com.google.appengine.api.urlfetch.URLFetchServiceFactory.getURLFetchService().fetch(req);
String line="";
String resp="";
resp=new String(response.getContent(), "UTF-8");
The above code is suitable for a scenario where the remote URL is accessed by GAE...However I have to also send an XML message containing name of function as well as input parameters (these are stored in variable named 'message')... How do I send that message to the remote URL, and after that obtain the response?
You should post the call method and parameters instead of GET. The method name and parameters go as XML.
See this http://xmlrpc.scripting.com/spec.html