I want to upload image to a server. URL:
http://asptest.expenseanywhere.com/eamobile/imageupload.aspx
Server requirer 5 fields for getting the response of successful upload that are: corporate id, username, password, etc. and image also. So how to send all these data to server and upload the image to server successfully? Please reply in details because I am new in Android and Java and I am not getting the idea how to do that. I am reading this article:
http://http://getablogger.blogspot.com/2008/01/android-how-to-post-file-to-php-server.html
but in this article only the image is sent to server. So how to write all the fields which I want to file and send all the fields to server for uploading the image? Help would be greatly appreciated.
I've used this to post form data, it might work for you:
final HttpUriRequest http_request = new HttpPost(url);
final List<NameValuePair> form_params = new ArrayList<NameValuePair>();
form_params.add(new BasicNameValuePair("key1", value1));
form_params.add(new BasicNameValuePair("key2", value2));
form_params.add(new BasicNameValuePair("key3", value3));
try {
((HttpPost) http_request).setEntity(new UrlEncodedFormEntity(form_params));
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
http_request.setHeader("Content-Type", "application/x-www-form-urlencoded");
then use an DefaultHttpClient with this request.
You have to upload it as a byte array. Check out how its done in this blog I found:
http://vikaskanani.wordpress.com/2011/01/29/android-image-upload-activity/
Heres the part your looking for here:
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bitmap.compress(CompressFormat.JPEG, 100, bos);
byte[] data = bos.toByteArray();
entity.addPart("photoId", new StringBody(getIntent()
.getStringExtra("photoId")));
entity.addPart("returnformat", new StringBody("json"));
entity.addPart("uploaded", new ByteArrayBody(data,
"myImage.jpg"));
entity.addPart("photoCaption", new StringBody(caption.getText()
.toString()));
Related
I'm trying to upload a photo from my Android Client to my Mobile Backend by encoding the image in base64 and sending it through the POST body of my client app. The photo doesnt get uploaded to the server.
My backend's method:
[HttpPost]
[Route("api/addactivity")]
public IHttpActionResult AddNewMediaActivity([FromBody]string base64String, string caption, string email, string type)
{
byte[] f = Convert.FromBase64String(base64String);
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
CloudConfigurationManager.GetSetting("StorageConnectionString"));
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
// Retrieve a reference to a container.
CloudBlobContainer container = blobClient.GetContainerReference("photos");
// Create the container if it doesn't already exist.
container.CreateIfNotExists();
container.SetPermissions(
new BlobContainerPermissions
{
PublicAccess = BlobContainerPublicAccessType.Blob
});
string uniqueBlobName = string.Format("photos" + "/" + "photos"+ "_{0}{1}", new Random().Next(1, 999999), new Random().Next(1, 999999));
// Retrieve reference to a blob named "myblob".
CloudBlockBlob blockBlob = container.GetBlockBlobReference(uniqueBlobName);
using (MemoryStream stream = new MemoryStream(f))
{
blockBlob.UploadFromStream(stream);
}
}
My Android Code:
BitmapFactory.Options options = new BitmapFactory.Options();
final Bitmap bitmap = BitmapFactory.decodeFile(fileUri.getPath(),
options);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] b = baos.toByteArray();
encodedImage = Base64.encodeToString(b, Base64.URL_SAFE);
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://mymobilewebaddress.azure-mobile.net/api/addactivity");
try {
// Request parameters and other properties.
List<NameValuePair> params = new ArrayList<NameValuePair>(2);
params.add(new BasicNameValuePair("Content-Type", "application/json"));
params.add(new BasicNameValuePair("ACCEPT", "application/json"));
params.add(new BasicNameValuePair("X-ZUMO-APPLICATION", mobileServiceAppId));
params.add(new BasicNameValuePair("base64String",image));
params.add(new BasicNameValuePair("caption",caption));
params.add(new BasicNameValuePair("email",email));
params.add(new BasicNameValuePair("type",type));
httppost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
//Execute and get the response.
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream instream = entity.getContent();
try {
// do something useful
} finally {
instream.close();
}
}
}
catch(Exception e)
{
}
However this does not upload the photo to my backend. There's no error either. The photo simply does not make it to the backend.
Am I sending the base64 string correctly via the POST?
What am I doing wrong guys?
Uploading a pic to BLOB storage . I got it after searching for hours .Take a look :-
Uploading the photo image is a multistep process:
First you take a photo, and insert a TodoItem row into the SQL database that contains new meta-data fields used by Azure Storage. A new mobile service SQL insert script asks Azure Storage for a Shared Access Signature (SAS). That script returns the SAS and a URI for the blob to the client. The client uploads the photo, using the SAS and blob URI.
So what is a SAS?
It's not safe to store the credentials needed to upload data to the Azure Storage service inside your client app. Instead, you store these credentials in your mobile service and use them to generate a Shared Access Signature (SAS) that grants permission to upload a new image. The SAS, a credential with a 5 minute expiration, is returned securely by Mobile Services to the client app. The app then uses this temporary credential to upload the image.
for further queries and detail analysis. Visit this official documentation https://azure.microsoft.com/en-us/documentation/articles/mobile-services-android-upload-data-blob-storage/
I am trying to upload an image from the android application to drupal. On drupal I have enabled the services module with rest server. My endpoint is androidrpc-endpoint. I have loged in successfully. However, now I am getting the error ( ["CSRF validation failed"] of type org.json.JSONArray cannot be converted to JSONObject). If anyone could point out the rror or give a me a tutorial to follow.
String filePath = "mnt/sdcard/application/AboutUS.jpg";
Bitmap bm = BitmapFactory.decodeFile(filePath);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] byteArrayImage = baos.toByteArray();
String encodedImage = Base64.encodeToString(byteArrayImage, Base64.DEFAULT);
HttpPost httpPost = new HttpPost("http://drupal/androidrpc-endpoint/file")
JSONObject json = new JSONObject();
JSONObject fileObject = new JSONObject();
try {
fileObject.put("file", encodedImage);
fileObject.put("filename", "AboutUS");
fileObject.put("uid",1);
fileObject.put("filepath", filePath);
json.put("file", fileObject);
StringEntity se = new StringEntity(json.toString());
se.setContentType(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
httpPost.setEntity(se);
//send the POST request
HttpResponse response = httpclient.execute(httpPost);
//read the response from Services endpoint
String jsonResponse = EntityUtils.toString(response.getEntity());
JSONObject jsonObject = new JSONObject(jsonResponse);//here is the error
int fid;
fid= jsonObject.getInt("fid");
return null;
}
catch(Exception e){
e.printStackTrace();
}
Any help please
I am assuming you already know how to set the CSRF token for login authentication, since you mention that you have been logging in successfully. That said, upon logging in, you should receive a response which contains a new token. That is the token that you should be using for the subsequent request to your Services Endpoint.
Also, if you have session authentication enabled, you should be attaching your session information as well ("session_name=sessid")
Lastly, I don't see why you are unable to create a JSONObject with a String as its constructor parameter. Perhaps it might be useful to troubleshoot by creating your JSONObject as an empty object, and then using the .put() method to assign the String to a key, prior to using Logcat or debug to investigate its contents.
I need to post a image to Twitter. I have integrated Twitter in my app. I need to tweet the image as such not as an URL link. I don't want to use TwitPic.
I used the following code to create the multipart entity. It give 404 error.
Bitmap bm = null;
String encodedImage = "";
try {
URL aURL = new URL("http://50.57.227.117/blacksheep/uploaded/Detailed_images/961314275649aladdins.jpg");
URLConnection conn = aURL.openConnection();
conn.connect();
InputStream is = conn.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is, 8192);
bm = BitmapFactory.decodeStream(bis);
bis.close();
is.close();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.PNG, 100, baos);
imageBytes = baos.toByteArray();
encodedImage = Base64.encodeToString(imageBytes, Base64.DEFAULT);
Log.v("encodedImage >>",encodedImage);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
HttpClient httpClient = new DefaultHttpClient();
HttpPost postRequest = new HttpPost(
"https://api.twitter.com/1.1/statuses/update_with_media.json");
ByteArrayBody bab = new ByteArrayBody(imageBytes, "forest.jpg");
MultipartEntity reqEntity = new MultipartEntity(
HttpMultipartMode.BROWSER_COMPATIBLE);
reqEntity.addPart("media", bab);
reqEntity.addPart("status", new StringBody("test image"));
postRequest.setEntity(reqEntity);
HttpResponse response = httpClient.execute(postRequest);
BufferedReader reader = new BufferedReader(new InputStreamReader(
response.getEntity().getContent(), "UTF-8"));
String sResponse;
StringBuilder s = new StringBuilder();
while ((sResponse = reader.readLine()) != null) {
s = s.append(sResponse);
}
System.out.println("Response: " + s);
// Update status
//twitter4j.Status response = twitter.updateStatus(encodedImage);
// twitter4j.Status response1 = twitter.updateStatus(status);
//Log.d("Status", "> " + response1.getText());
} catch (TwitterException e) {
// Error in updating status
Log.d("Twitter Update Error", e.getMessage());
}
First attempt:
So it seemed like you were using Apache's old http client to make a request external to the library you were using to help integrate with twitter, twitter4j. I assumed you were using a version prior to 3.03 which is latest, and didn't want you to upgrade. You see, update_with_media is quite new, so I didn't think your version had implemented it.
The problem with what you were doing is that twitter uses oauth for authentication. So you'd need to "sign" a request with the access token you'd obtained. Twitter4j, AFAIK, does this for you. You can't use a seperate client to make some calls without reference to your nice helper library without breaking authentication.
The endpoint, ../update_with_media is defined to update a status for the currently authenticating user. I suspect that, since there was no access token and no user in your request, that endpoint doesn't even make sense, so twitter were interpreting it as a 404 (not found) rather than a 401 (unauthorized)- funny.
So the first attempt was not to require you to upgrade to twitter4j. It's a pain to upgrade sometimes! Instead, you can hack with the library as is detailed with this blog. But that wasn't easy as the libraries were different.
So, something else we could try, if you really wanted to make a seperate request to twitter4j, was to actually do the signing, perhaps using scribe to make it easier.... roughly:
final OAuthService myTwitterService = TwitterClient.getTwitterClient().getService();
final OAuthRequest aNiceOAuthRequest = new org.scribe.model.OAuthRequest(
YOURPOST, THATURL);
etc.
Second attempt:
But let's not do all this- turns out you had the latest version of twitter4j anyway. Sorry for going down a cul-de-sac first- I shouldn't have assumed, but I've included the above for help for anybody else should they need it.
It turns out the latest version has implemented this endpoint- documentation here. Except it takes a StatusUpdate object instead. So you want to do something like:
final StatusUpdate statusUpdate = new StatusUpdate("Hallee hallo my status java.lang.String here...");
// now do as you did until:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.PNG, 100, baos);
imageBytes = baos.toByteArray();
encodedImage = Base64.encodeToString(imageBytes, Base64.DEFAULT);
// then flip the stream
byte[] myTwitterUploadBytes = bos.toByteArray();
ByteArrayInputStream bis = new ByteArrayInputStream(myTwitterUploadBytes);
// doo and double check your encoding etc, similar to in your question..
statusUpdate.setMedia("give me a java.lang.String name", bis);
// then continue just using twitter for j- update status as you would
//... get twitter etc...
//
twitter4j.Status response = twitter.updateStatus(statusUpdate);
Haven't currently got a box on me to test- should be about right. If it still gives 404s, what is the error code in the response? Are you authenticated?
If that doesn't work, we can try some of the above too as a back up.
Hope this helps,
best,
Tom.
Using 4.0.3 (perhaps earlier) it's very simple to embed images in a tweet with twitter4j:
Twitter twtobj;
StatusUpdate stsupd;
Status stsres;
twtobj=twitterFactory.getInstance();
twtobj.setOAuthConsumer(csmkey,csmsec);
twtobj.setOAuthAccessToken(new AccessToken(acstkn,acssec));
stsupd=new StatusUpdate(msgtxt);
if(medurls.length>0) {
long[] medidns=new long[medurls.length];
for(int xa=0; xa<medurls.length; xa++) {
String medurl=Util.resolveRelativeUrl(medurls[xa]);
InputStream imgstm=null;
try {
imgstm=new URL(medurl).openConnection().getInputStream();
medidns[xa]=twtobj.uploadMedia(medurl,imgstm).getMediaId(); // this actually uploads the image to Twitter at this point
}
catch(MalformedURLException thr) { throw new ShfFail(Fail.IMAGE_URL ,"The media URL is not valid: " +medurl+" ("+thr.getMessage()+")"); }
catch(IOException thr) { throw new ShfFail(Fail.IMAGE_READ,"The media could not be read: "+medurl+" ("+thr.getMessage()+")"); }
finally { GenUtil.close(imgstm); }
}
stsupd.setMediaIds(medidns);
}
stsres=twtobj.updateStatus(stsupd);
Note that up to 4 images, or 1 animated GIF, or 1 video are allowed, as of 2015-06-10.
Note also that I am capturlng the image streams to close them explicitly in the outer block (not shown). This may be unnecessary, but I can't find positive confirmation of that.
If anyone cares, resolveRelativeUrls is a convenience to allow a relative path to be resolved as a file URL from the current folder:
static public String resolveRelativeUrl(String url) {
if(!TextUtil.stringCT(url,"://")) {
url=new File(url).getAbsoluteFile().toURI().toString();
}
return url;
}
The utility method stringCT is case-insensitive contains.
I am developing an app-engine connected android project using the eclipse plugin. One aspect of the app is to allow user Alpha to send pictures to user Bravo. To do that I have the following setup:
User Alpha posting:
send image to my app engine server through endpoints
server stores image in blob store
server stores blobkey in datastore
User Bravo getting:
server gets blobkey from datastore
server gets image using blob key
server sends image to android app using endpoints
This setup takes upward of two (2) minutes from when my android app sends an image to when I can see it in the blob sore. Needless to say this is completely unacceptable.
My server is processing the image programmatically, thru the following code:
public static BlobKey toBlobstore(Blob imageData) throws FileNotFoundException, FinalizationException, LockException, IOException {
if (null == imageData)
return null;
// Get a file service
FileService fileService = FileServiceFactory.getFileService();
// Create a new Blob file with mime-type "image/png"
AppEngineFile file = fileService.createNewBlobFile("image/jpeg");// png
// Open a channel to write to it
boolean lock = true;
FileWriteChannel writeChannel = fileService.openWriteChannel(file, lock);
// This time we write to the channel directly
writeChannel.write(ByteBuffer.wrap
(imageData.getBytes()));
// Now finalize
writeChannel.closeFinally();
return fileService.getBlobKey(file);
}
Does anyone know how I can either adapt the official example to use endpoints (in the case where I must use my app-engine instances) or use getServingUrl (bypassing my instances) to store and serve my blobs? Please, instead of words, include the code. Thanks.
I'll share how I'm doing this. I'm not using the google-cloud-endpoints, but just my own rest based api, but it should be the same idea either way.
I'll lay it out step by step with code, hopefully it will be clear.
You'd simply adapt the way you send your requests to use endpoints instead of doing it more generic like in this example. I'm including some boilerplate, but excluding try/catch,error checking etc for brevity.
Step 1 (client)
First client requests an upload url from server:
HttpClient httpclient = new DefaultHttpClient();
HttpConnectionParams.setConnectionTimeout(httpclient.getParams(), 10000); //Timeout Limit
HttpGet httpGet = new HttpGet("http://example.com/blob/getuploadurl");
response = httpclient.execute(httpGet);
Step 2 (server)
On the server side the upload request servlet would look something like this:
String blobUploadUrl = blobstoreService.createUploadUrl("/blob/upload");
res.setStatus(HttpServletResponse.SC_OK);
res.setContentType("text/plain");
PrintWriter out = res.getWriter();
out.print(blobUploadUrl);
out.flush();
out.close();
note the argument to createUploadUrl. This is where the client will be
redirected once the actual upload has been completed. That's where
you'll handle storing the blobkey and/or serving url and returning it to the client. You'll have to map a servlet to that url, which will handle step 4
Step 3 (client)
Back to the client again to send the actual file to the upload url using the url returned from step 2.
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(uploadUrlReturnedFromStep2);
FileBody fileBody = new FileBody(thumbnailFile);
MultipartEntity reqEntity = new MultipartEntity();
reqEntity.addPart("file", fileBody);
httppost.setEntity(reqEntity);
HttpResponse response = httpclient.execute(httppost)
Once this request is sent to the servlet in step 2, it will be redirected to the servlet you specified in the createUploadUrl() earlier
Step 4 (server)
Back to the server side:
This is the servlet handling the url mapped to blob/upload. We will here return the blobkey and serving url to the client in a json object:
List<BlobKey> blobs = blobstoreService.getUploads(req).get("file");
BlobKey blobKey = blobs.get(0);
ImagesService imagesService = ImagesServiceFactory.getImagesService();
ServingUrlOptions servingOptions = ServingUrlOptions.Builder.withBlobKey(blobKey);
String servingUrl = imagesService.getServingUrl(servingOptions);
res.setStatus(HttpServletResponse.SC_OK);
res.setContentType("application/json");
JSONObject json = new JSONObject();
json.put("servingUrl", servingUrl);
json.put("blobKey", blobKey.getKeyString());
PrintWriter out = res.getWriter();
out.print(json.toString());
out.flush();
out.close();
Step 5 (client)
We'll get the blobkey and serving url from the json and then send it along with user id etc to store in the datastore entity.
JSONObject resultJson = new JSONObject(resultJsonString);
String blobKey = resultJson.getString("blobKey");
String servingUrl = resultJson.getString("servingUrl");
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("userId", userId));
nameValuePairs.add(new BasicNameValuePair("blobKey",blobKey));
nameValuePairs.add(new BasicNameValuePair("servingUrl",servingUrl));
HttpClient httpclient = new DefaultHttpClient();
HttpConnectionParams.setConnectionTimeout(httpclient.getParams(), 10000);
HttpPost httppost = new HttpPost(url);
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httppost);
// Continue to store the (immediately available) serving url in local storage f.ex
Step 6 (server)
Actually storing everything in the datastore (using objectify in this example)
final String userId = req.getParameter("userId");
final String blobKey = req.getParameter("blobKey");
final String servingUrl = req.getParameter("servingUrl");
ExampleEntity entity = new ExampleEntity();
entity.setUserId(userId);
entity.setBlobKey(blobKey);
entity.setServingUrl(servingUrl);
ofy().save().entity(entity);
I hope this makes things more clear. If someone wants to edit the answer to use cloud endpoints instead of this more generic example, feel free :)
About the serving url
The serving url is a great way to serve images to your clients, because of the way it can dynamically scale images on the fly. For example you can send smaller images to your LDPI users by simply appending =sXXX at the end of the serving url. Where XXX is the pixel size of the largest dimension of your image. You completely avoid your instances and only pay for bandwidth, and the user only downloads what she needs.
PS!
It should be possible to stop at step 4 and just store it directly there, by passing along userId f.ex in step 3. Any parameters are supposed to be sent along to Step 4, but I did not get that to work, so this is how I do it at the moment, so I'm sharing it this way since i know it works.
I used the answer of this question to build my own system that uses AppEngine Endpoints. Unlike the posts above, I want to have a clean API that directly transmits the image (as byte array) to Google Endpoint and the upload to BlobstorageService is done on the backend side. The benefit of that is that i have an atomic API. The drawback obviously the load on the server as well as the heavy marshalling operations on the client.
Android - load, scale and serialize image and upload to endpoints
void uploadImageBackground(Bitmap bitmap) throws IOException {
// Important! you wanna rescale your bitmap (e.g. with Bitmap.createScaledBitmap)
// as with full-size pictures the base64 representation would not fit in memory
// encode bitmap into byte array (very resource-wasteful!)
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
bitmap.recycle();
bitmap = null;
stream = null;
// Note: We encode ourselves, instead of using image.encodeImageData, as this would throw
// an 'Illegal character '_' in base64 content' exception
// See: http://stackoverflow.com/questions/22029170/upload-photos-from-android-app-to-google-cloud-storage-app-engine-illegal-char
String base64 = Base64.encodeToString(byteArray, Base64.DEFAULT);
byteArray = null;
// Upload via AppEngine Endpoint (ImageUploadRequest is a generated model)
ImageUploadRequest image = new ImageUploadRequest();
image.setImageData(base64);
image.setFileName("picture.png");
image.setMimeType("image/png");
App.getMyApi().setImage(image).execute();
}
Backend API Endpoint - Upload image to BlobstorageService
#ApiMethod(
name = "setImage",
path = "setImage",
httpMethod = ApiMethod.HttpMethod.POST
)
public void saveFoodImageForUser(ImageUploadRequest imageRequest) throws IOException {
assertNotEmpty(userId, "userId");
assertNotNull(imageRequest, "imageRequest");
// create blob url
BlobstorageService blobService = BlobstoreServiceFactory.getBlobstoreService();
String uploadUrl = blobService.createUploadUrl("/blob/upload");
// create multipart body containing file
HttpEntity requestEntity = MultipartEntityBuilder.create()
.addBinaryBody("file", imageRequest.getImageData(),
ContentType.create(imageRequest.getMimeType()), imageRequest.getFileName())
.build();
// Post request to BlobstorageService
// Note: We cannot use Apache HttpClient, since AppEngine only supports Url-Fetch
// See: https://cloud.google.com/appengine/docs/java/sockets/
URL url = new URL(uploadUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.addRequestProperty("Content-length", requestEntity.getContentLength() + "");
connection.addRequestProperty(requestEntity.getContentType().getName(), requestEntity.getContentType().getValue());
requestEntity.writeTo(connection.getOutputStream());
// BlobstorageService will forward to /blob/upload, which returns our json
String responseBody = IOUtils.toString(connection.getInputStream());
if(connection.getResponseCode() < 200 || connection.getResponseCode() >= 400) {
throw new IOException("HTTP Status " + connection.getResponseCode() + ": " + connection.getHeaderFields() + "\n" + responseBody);
}
// parse BlopUploadServlet's Json response
ImageUploadResponse response = new Gson().fromJson(responseBody, ImageUploadResponse.class);
// save blobkey and serving url ...
}
Servlet that handles callback from BlobstorageService
public class BlobUploadServlet extends HttpServlet {
#Override
public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
BlobstorageService blobService = BlobstoreServiceFactory.getBlobstoreService();
List<BlobKey> blobs = blobService.getUploads(req).get("file");
if(blobs == null || blobs.isEmpty()) throw new IllegalArgumentException("No blobs given");
BlobKey blobKey = blobs.get(0);
ImagesService imagesService = ImagesServiceFactory.getImagesService();
ServingUrlOptions servingOptions = ServingUrlOptions.Builder.withBlobKey(blobKey);
String servingUrl = imagesService.getServingUrl(servingOptions);
res.setStatus(HttpServletResponse.SC_OK);
res.setContentType("application/json");
// send simple json response (ImageUploadResponse is a POJO)
ImageUploadResponse result = new ImageUploadResponse();
result.setBlobKey(blobKey.getKeyString());
result.setServingUrl(servingUrl);
PrintWriter out = res.getWriter();
out.print(new Gson().toJson(result));
out.flush();
out.close();
}
}
The only thing left to do is to bind /blob/upload to UploadBlobServlet.
Note: This doesn't seem to work when AppEngine is running locally (if executed locally, then the POST to BlobstorageService would always return a 404 NOT FOUND)
Since I tried with many way to do the callback service in the api of endpoint, I abort that aproach. However, I could solve that problem making a parallel servlet to the api endpoint, it only needs define the class server and add it web.xml configuration. Here my solution:
1 Enpoint Service for get the URL for upload:
Then the service coudl be protected with clientId
#ApiMethod(name = "getUploadURL", httpMethod = HttpMethod.GET)
public Debug getUploadURL() {
String blobUploadUrl = blobstoreService.createUploadUrl("/update");
Debug debug = new Debug();
debug.setData(blobUploadUrl);
return debug;
}
2. Now the Client can call to endpoint for get the upload URL:
Maybe some like this (for android use you client library enpoint too):
gapi.client.debugendpoint.getUploadURL().execute();
3. The next step is todo a post to url catched in last step:
You can do that with a httpClient of android, again, in my case I need upload from a web then I use a form, and onChangeFile() event callback for get the uploadurl (using step 3) then when it response to change the form parameters "action" and "codeId" before that someone decide do click on submit button:
<form id="submitForm" action="put_here_uploadUrl" method="post" enctype="multipart/form-data">
<input type="file" name="image" onchange="onChangeFile()">
<input type="text" name="codeId" value='put_here_some_dataId'>
<input type="submit" value="Submit"></form>
4 Finally the paralele servlet class:
#SuppressWarnings("serial")
public class Update extends HttpServlet{
public void doPost(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
String userId = req.getParameter("codeId");
List<BlobKey> blobs = BSF.getService().getUploads(req).get("image");
BlobKey blobKey = blobs.get(0);
ImagesService imagesService = ImagesServiceFactory.getImagesService();
ServingUrlOptions servingOptions = ServingUrlOptions.Builder.withBlobKey(blobKey);
String servingUrl = imagesService.getServingUrl(servingOptions);
resp.setStatus(HttpServletResponse.SC_OK);
resp.setContentType("application/json");
JSONObject json = new JSONObject();
try {
json.put("imageUrl", servingUrl);
json.put("codeId", "picture_of_"+userId);
json.put("blobKey", blobKey.getKeyString());
} catch (JSONException e){
e.printStackTrace();
}
PrintWriter out = resp.getWriter();
out.print(json.toString());
out.flush();
out.close();
}
}
and add to web.xml, where com.apppack is the package of Update Class
<servlet>
<servlet-name>update</servlet-name>
<servlet-class>com.apppack.Update</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>update</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
I have an idea for an app and am currently learning Android development. I'm fairly familiar with creating simple standalone apps.
I'm also familiar with PHP and webhosting.
What I want to do is, make an android app send an image to a server via the internet and make the server return a processed image. I have no clue how I'd do that.
Can you please tell me how can I go about achieving this or which topics should I look into? Also, what scripts can I use to do the processing on the web server? Particularly, can I use PHP or Java?
Thanks!
For Image Uploading
///Method Communicate with webservice an return Yes if Image uploaded else NO
String executeMultipartPost(Bitmap bm,String image_name) {
String resp = null;
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bm.compress(CompressFormat.JPEG, 75, bos);
byte[] data = bos.toByteArray();
HttpClient httpClient = new DefaultHttpClient();
HttpPost postRequest = new HttpPost("domain.com/upload_image.php");
ByteArrayBody bab = new ByteArrayBody(data, image_name);
MultipartEntity reqEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
reqEntity.addPart("uploaded", bab);
reqEntity.addPart("photoCaption", new StringBody("sfsdfsdf"));
postRequest.setEntity(reqEntity);
HttpResponse response = httpClient.execute(postRequest);
BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
String sResponse;
StringBuilder s = new StringBuilder();
while ((sResponse = reader.readLine()) != null) {
s = s.append(sResponse);
}
resp=s.toString();
} catch (Exception e) {
// handle exception here
Log.e(e.getClass().getName(), e.getMessage());
}
return resp;
}
//PHP Code
<?php
$target = "upload/";
$target = $target . basename( $_FILES['uploaded']['name']) ;
$ok=1;
if(move_uploaded_file($_FILES['uploaded']['tmp_name'], $target))
{
echo "yes";
}
else {
echo "no";
}
?>
Normally we do it with http connection, you can pass the image in the
post params, for further reference please see the link
You have to create a simple php web service which accepts parameter as image bytes and which process the image and store in server. For this android app will send image data in bytes to the server using HttpPost.
For retrieving purpose you have to create a other web service which will output the file name of image from where android app can retrieve the image