We're trying to build application which will store images to blobstore.
I used the code from here and added it to endpoint project.
Now the /uploaded servlet returns to client JSONObject like this:
json.put("servingUrl", servingUrl);
json.put("blobKey", blobKey);
There is a PictureEntity class. Where the field blobKey is of the type BlobKey and I can send another HttpPost request with all needed data to server, get the needed String from html entity and apply
picture.setBlobKey(blobKey); on server side.
But since I use EndPoints I don't want to transfer all the data again to another servlet on the server. I want to use endpoints. And it seems that they should somehow support BlobKey type.
At least GAE creates model for them but when I try to do the same on client side I always get an error:
The method setBlobKey(BlobKey) in the type PictureEntity is not
applicable for the arguments (String)
Any help would be appreciated. Thanks!
Related
Sorry, but I wanted to confirm if there was a way to do this without having to serialize to JSON, which is what I kept on reading online.
The problem that I am having is that I want to test with Postman my email service which has a Email dto of
{
String toEmail
String subjectLine
String content
List<File> attachments (Text files can be used for test if that helps)
}
Previously, before adding the list of files, I could use Postman to test with raw under the body tab of postman and sending in a json. However, I don't think I can add an object with that same method. When trying out form-data though, I am getting that the request entity is in a format not supported.
Currently, my service is only taking in a EmailDto as its resource.
Does anyone have suggestions or thoughts?
I need to send the json object in get request. I installed chrome Postman extension but i am not getting how can i send json object in GET request ?
Postman provides the way to send json data in Post request by adding the header as application/json and then add the json data under raw form.
How to send the json data in GET request ? Do i need to append it in URL ?
It's bad solution to send any objects using get request. But you can send it as a url parameter using url encoding:
String url = "http://example.com/query?json=" + URLEncoder.encode(json, "UTF-8");
In POSTMAN you can send body data in GET request. If you try to append in the URL using url encoding you will get error.
Try to convert json object into string and send it in the URL parameters and see if it works.
Also if your backend server allows only to send data as URL parameters and your URL is long (i.e approx 2048 characters) then I am not sure whether this will work.
If above solution doesn't work then I think you can achieve this using curl. CURL is a tool for doing all sorts of URL manipulations and transfers. You can generate cURL code using Postman. Here is the reference
You can use google chrome Postman Extension
it allows you to send and see any type of data.
I'm currently using org.apache.http.entity.mime.MultipartEntityBuilder. The following don't work:
.addPart("key", new StringBody(jsonObject.toString()))
.addTextBody("key", jsonObject.toString())
.addTextBody("key", jsonObject.toString(), ContentType.APPLICATION_JSON)
Here, jsonObject is an org.json.JSONObject.
Non-nested fields and the image field validates correctly, but the nested fields don't seem to get filled out (the server returns "This field is required.").
Solutions that don't use the MultipartEntityBuilder are welcome as well.
I don't know anything about Apache's MultipartEntityBuilder.
But you could always send your image as a Base64 field in your json object. In the server, you'd need to map that to a byte[] field.
Multipart data does not play well with nested json. I settled for flattening the nested fields in the server API. Then, building the request still using MultipartEntityBuilder:
HttpEntity entity = MultipartEntityBuilder.create()
.addTextBody("inner_key1", jsonObject.get("inner_key1").toString())
.addTextBody("inner_key2", jsonObject.get("inner_key2").toString())
.addTextBody("inner_key3", jsonObject.get("inner_key3").toString())
.addBinaryBody("image", new File(imagePath))
.build();
I have an app that allows users to save blobs in the blobstore. I have a schema that does so presently, but I am interested in something simpler and less twisted. For context, imagine my app allows users to upload the picture of an animal with a paragraph describing what the animal is doing.
Present schema
User calls my endpoint api to save the paragraph and name of the animal in entity Animal. Note: The Animal entity actually has 4 fields ( name, paragraph, BlobKey, and blobServingUrl as String). But the endpoint api only allows saving of the two mentioned.
Within the endpoint method, on app-engine side, after saving name and paragraph I make the following call to generate a blob serving url, which my endpoint method returns to the caller
#ApiMethod(name = "saveAnimalData", httpMethod = HttpMethod.POST)
public String saveAnimalData(AnimalData request) throws Exception {
...
BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();
String url = blobstoreService.createUploadUrl("/upload");
return url;
}
On the android side, I use a normal http call to send the byte[] of the image to the blobstore. I use apache DefaultHttpClient(). Note: the blobstore, after saving the image, calls my app-engine server with the blob key and serving url
I read the response from the blobstore (blobstore called my callback url) using a normal java servlet, i.e. public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException. From the servlet, I put the BlobKey and blobServingUrl into the Animal entity for the associated animal. (I had passed some meta data to the blobstore, which I use as markers to identify the associated animal entity).
Desired Schema
This is where your response comes in. Essential, I would like to eliminate the java servlet and have my entire api restricted to google cloud endpoint. So my question is: how would I use my endpoint to execute steps 3 and 4?
So the idea would be to send the image bytes to the endpoint method saveAnimalData at the same time that I am sending the paragraph and name data. And then within the endpoint method, send the image to the blobstore and then persist the BlobKey and blobServingUrl in my entity Animal.
Your response must be in java. Thanks.
I see two questions in one here :
Can Google Cloud Endpoints handle multipart files ? -> I don't know about this TBH
Is there a simpler process to store blobs than using the BlobStoreService?
It depends on the size of your image. If you limit your users to < 1MB files, you could just store your image as a Blob property of your Animal entity. It would allow you to bypass the BlobStoreService plumbering. See : https://developers.google.com/appengine/docs/java/datastore/entities?hl=FR
This solution still depends on how the Cloud Endpoint would handle the multipart file as a raw byte[]...
We encountered the same issue with GWT + Google App Engine in 2009, and it was before the BlobStoreService was made available.
GWT RPC and Cloud Endpoints interfaces share some similarities, and for us it was not possible. We had to create a plain HTTP Servlet, and use a Streaming Multipart file resolver beacause the one from Apache's HTTP Commons used the file system.
My main question is how can I pass JSON as well as File to post request to REST API? What needs in Spring framework to work as client and wait for response by passing post with JSON and File?
Options:
Do I need to use FileRepresentation with ClientResource? But how can I pass file as well as JSON?
By using RestTemplate for passing both JSON as well as File? How it can be used for posting JSON as well as File?
Any other option is available?
Sounds like an awful resource you're trying to expose. My suggestion is to separate them into 2 different requests. Maybe the JSON has the URI for the file to then be requested…
From a REST(ish) perspective, it sounds like the resource you are passing is a multipart/mixed content-type. One subtype will be application/json, and one will be whatever type the file is. Either or both could be base64 encoded.
You may need to write specific providers to serialize/deserialize this data. Depending on the particular REST framework, this article may help.
An alternative is to create a single class that encapsulates both the json and the file data. Then, write a provider specific to that class. You could optionally create a new content-type for it, such as "application/x-combo-file-json".
You basically have three choices:
Base64 encode the file, at the expense of increasing the data size
by around 33%.
Send the file first in a multipart/form-data POST,
and return an ID to the client. The client then sends the metadata
with the ID, and the server re-associates the file and the metadata.
Send the metadata first, and return an ID to the client. The client
then sends the file with the ID, and the server re-associates the
file and the metadata.