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.
Related
I am developing an android app where user logs on to his/her account. After logging in I will receive XSRF token and Laravel Session Id to recognise the specific user. I have to send these tokens for every request I send to the API's to get the appropriate information. But when I am sending the required details as shown in the image, I am getting HTMl file as response instead of getting JSON Object. I was seriously stuck at this problem. Correct Solution may take forward the whole app.
class RegisterConnection extends AsyncTask<String,String,JSONObject> {
protected JSONObject doInBackground(String... arg0) {
JSONObject output = new JSONObject();
DefaultHttpClient client = new DefaultHttpClient();
HttpConnectionParams.setConnectionTimeout(client.getParams(), 5000); //Timeout Limit
HttpResponse response = null;
try {
HttpGet get = new HttpGet(statsURL);
get.setHeader("Accept", "application/json");
CookieStore store = new BasicCookieStore();
BasicClientCookie cookie1 = new BasicClientCookie("XSRF-TOKEN", XSRF);
BasicClientCookie cookie2 = new BasicClientCookie("laravel_session", laravel);
store.addCookie(cookie1);
store.addCookie(cookie2);
client.setCookieStore(store);
response = client.execute(get);
if(response!=null){
InputStream in = response.getEntity().getContent();
String resultstring = Utilities.convertStreamToString(in);
Log.i("Result1", resultstring);
output = new JSONObject(resultstring);
Log.i("Result2", output.toString());
}
} catch(Exception e) {
e.printStackTrace();
try {
output.put("sai","error");
Log.i("MainActivity", output.toString());
} catch (JSONException e1) {
e1.printStackTrace();
}
return output;
}
return output;
}
These are the server requirements
http://imgur.com/OY9Q673
This is the Output received
http://imgur.com/IB5AEcT
As far as I can tell, there is nothing wrong with your Android client code.
You are getting HTML from the server so the main reason could be that your Laravel server is rendering the views and sending you back html instead of JSON. Instead of rendering the views on the server, you should send JSON response on your Laravel server side.
Add Jsoup dependency in your gradle file
implementation 'org.jsoup:jsoup:1.11.2'
Document document = Jsoup.parse("http://imgur.com/IB5AEcT");
Elements el = doc.select("button");
Log.i("..........",""+el.attr("data-invite-details"));
Jsoup tutorial
http://jsoup.org/apidocs/org/jsoup/Jsoup.html
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 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
I'm trying to upload an image file from an android device to my drupal website using services module
I can log-in succesfully:
HttpParams connectionParameters = new BasicHttpParams();
int timeoutConnection = 3000;
HttpConnectionParams.setConnectionTimeout(connectionParameters, timeoutConnection);
int timeoutSocket = 5000;
HttpConnectionParams.setSoTimeout(connectionParameters, timeoutSocket);
httpClient = new DefaultHttpClient(connectionParameters);
HttpPost httpPost = new HttpPost(serverUrl+"user/login");
JSONObject json = new JSONObject();
try{
json.put("password", editText_Password.getText().toString());
json.put("username", editText_UserName.getText().toString());
StringEntity se = new StringEntity(json.toString());
se.setContentType(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
httpPost.setEntity(se);
//Execute HTTP post request
HttpResponse response = httpClient.execute(httpPost);
int status_code = response.getStatusLine().getStatusCode();
...
...
}
catch(Exception ex)
{
}
via response object I can get session name session id , user id and many other info.
after the login , I set no session info by myself through my HttpGet object , but use the same DefaultHttpClient, I can magically retrieve a node using the following code:
HttpGet httpPost2 = new HttpGet(serverUrl+"node/537.json");
HttpResponse response2 = httpClient.execute(httpPost2);
this made me think that, httpClient object stored the session info for me automatically.
because if I dont login first or use a new HttpClient object and try to retrieve the node, I get a 401 error.
However when I try to upload an image file as follows after logging in:
httpPost = new HttpPost(serverUrl+"file/");
json = new JSONObject();
JSONObject fileObject = new JSONObject();
fileObject.put("file", photodata); //photodata is a byte[] that is set before this point
fileObject.put("filename", "myfirstfile");
fileObject.put("filepath", "sites/default/files/myfirstimage.jpg");
json.put("file", fileObject);
se = new StringEntity(json.toString());
se.setContentType(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
httpPost.setEntity(se);
//Execute HTTP post request
response = httpClient.execute(httpPost);
status_code = response.getStatusLine().getStatusCode();
I get 401 error although I'm logged in and using the same HttpClient object.
I also tried adding :
httpPost.setHeader("Cookie", SessionName+"="+sessionID);
which again gives me 401 error.
I'm also not sure whether I'm using the correct url, because I'm trying to use file.create method, but writing the url as "myip:myport/rest/file/create" gives wrong address.
My aim is to upload an image to a users node, so I guess after succesfully adding the file, I'll use node.create right?
I hope someone will help me get through this.
I found when I first started doing this that most of my errors were due to not authenticating correctly.. I'm not sure your method is correct.. I know this works.
Using Drupal Services 3, I login as such and then store my session cookie into shared preferences. dataOut is a JSON object which holds the needed user login, and password information.
String uri = URL + ENDPOINT + "user/login";
HttpPost httppost = new HttpPost(uri);
httppost.setHeader("Content-type", "application/json");
StringEntity se;
try {
se = new StringEntity(dataOut.toString());
se.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE,
"application/json"));
httppost.setEntity(se);
HttpResponse response = mHttpClient.execute(httppost);
mResponse = EntityUtils.toString(response.getEntity());
// save the sessid and session_name
JSONObject obj = new JSONObject(mResponse);
SharedPreferences settings = PreferenceManager
.getDefaultSharedPreferences(mCtx);
SharedPreferences.Editor editor = settings.edit();
editor.putString("cookie", obj.getString("session_name") + "="
+ obj.getString("sessid"));
editor.putLong("sessionid_timestamp", new Date().getTime() / 100);
editor.commit();
} catch { //all of my catches here }
Once I have my session id stored.. I go about performing tasks on drupal like this.. The following code posts a node. I use the function getCookie() to grab the session cookie if it exists.. if not, then I log in, or if it's expired, I log in. (note, you need to set the cookie expire time in your drupal settings.php file (I think that's where it is if I remember correctly)
String uri = URL + ENDPOINT + "node";
HttpPost httppost = new HttpPost(uri);
httppost.setHeader("Content-type", "application/json");
String cookie = this.getCookie(mCtx);
httppost.setHeader("Cookie", cookie);
StringEntity se;
try {
se = new StringEntity(dataOut.toString());
httppost.setEntity(se);
HttpResponse response = mHttpClient.execute(httppost);
// response is here if you need it.
// mResponse = EntityUtils.toString(response.getEntity());
} catch { //catches }
The getCookie() function that keeps your cookie uptodate and working..
/**
* Takes the current time, the sessid and determines if we are still part of
* an active session on the drupal server.
*
* #return boolean
* #throws InternetNotAvailableException
* #throws ServiceNotAvailableException
*/
protected String getCookie(Context ctx)
throws InternetNotAvailableException {
SharedPreferences settings = PreferenceManager
.getDefaultSharedPreferences(mCtx);
Long timestamp = settings.getLong("sessionid_timestamp", 0);
Long currenttime = new Date().getTime() / 100;
String cookie = settings.getString("cookie", null);
//mSESSION_LIFETIME is the session lifetime set on my drupal server
if (cookie == null || (currenttime - timestamp) >= mSESSION_LIFETIME) {
// the following are the classes I use to login.
// the important code is listed above.
// mUserAccount is the JSON object holding login,
// password etc.
JSONObject mUserAccount = UserAccount.getJSONUserAccount(ctx);
call(mUserAccount, JSONServerClient.USER_LOGIN);
return getCookie(ctx);
} else {
return cookie;
}
}
This really should enable you to take advantage of all that Services has to offer. Make sure your endpoints are correct, and also make sure your permissions are set. I cursed for hours before I realized I had not granted perms to make nodes to users.
So once you are logged in.. To upload a file to Drupal Services I use the following code to first convert the image to byteArray.. and then to Base64.
tring filePath = Environment.getExternalStorageDirectory()+ "/test.jpg";
imageView.setImageDrawable(Drawable.createFromPath(filePath));
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);
Once you have the encodedImage. Construct a JSON Object with the keys, file (required), filename (optional, but recommended), filesize (optional) and uid (optional, the poster I presume) JSON would therefore look like this at its simplist required form {"file":encodedImage}. Then, after making sure you have enabled the file resource on your server, POST the data to my-server/rest-endpoint/file. The response will include a fid in JSON. You can then assign this fid to the image field of a node you subsequently create using the node resource.
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()));