I'm currently sending an image to my server by encoding it into a base64 string like this: https://gist.github.com/fabdarice/a4006a97171cc415892e
However, when I'm looking at the HTTP POST request, I'm seeing something like this :
{"login"=>"Jerem", "mobile_upload_file"=>"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB\nAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/2wBDAQEBAQEBAQEBAQEBAQEBAQEBAQEB\nAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/wAARCAQ4BDgDASIA\nAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQA\nAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3\nODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWm\np6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEA\nAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3....................................}
This goes on for a while, (around 1 millions characters) and it seems to make my server laggy.
I was wondering if this is a normal behavior to see that amount of characters sent? If not, how am I supposed to implement the process of sending an image to a server?
Thanks for your help
You can send image in FileBody by Multipart entity like this...
public String sendMultipartRequestToServer(BusinessDataObject dataObject,String url) {
String responseString=null;
HttpResponse response;
HttpClient client=new DefaultHttpClient();
HttpPost post=new HttpPost(url);
HttpConnectionParams.setConnectionTimeout(client.getParams(),50000);
MultipartEntity multipartEntity=new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
try {
multipartEntity.addPart(KEY_EMAIL,new StringBody(dataObject.getEmail()));
multipartEntity.addPart(KEY_PASSWORD, new StringBody(dataObject.getPassword()));
multipartEntity.addPart(KEY_IMAGE,new FileBody(new File(Here your image path on your memory)));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
//Setting parameter to post method
post.setEntity(multipartEntity);
try {
response=client.execute(post);
InputStream inputStream=response.getEntity().getContent();
responseString=convertStreamToString(inputStream);
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return responseString;
}
If you will not find the class MultipartEntity .Then you have to add HttpMime.jar in your project .It is the best way to send images so far i know here no need to convert image in Base64.You can just pass the url of selected image to FileBody.
Related
I have a Python/Django server that is the API for a web service.
I'm building an Android application that will communicate with the API and authenticate users, and enable them do all pulls/pushes from the server.
My trouble is with the particular communication with the server. Currently I use my WiFi network, and run the server like so python manage.py runserver 192.168.1.3:8000 so that it is available to any test device on my LAN.
The API is written so it returns http status messages with every response, so that I can tell the success or failure of a request before parsing the JSON reply.
On my Android side, I have used HttpURLConnection because it has the getHeaderField(null) method that I use to pick the http status message from the response. I get a status message 200 [success] when I 'ping' my server - this is a sort-of proof of concept.
My real issue is authentication. My API requires I send it a JSON with data, and it returns a JSON response [with an http status message in the head].
I can't seem to figure out how to do this. The JSON action I've seen around the interwebs are merely picking, or posting.
I am wondering how I can POST and pick up a response from the server.
Extra information
- Server supports HEAD and GET and OPTIONS.
- Assuming server home is 192.168.1.3, user login/register would be in 192.168.1.3/user, events would be in 192.168.1.3/events and so on..
- This was the closest I got to figuring out a solution, but not quite..
CODE from the AsyncTask
protected JSONObject doInBackground(String... params) {
publishProgress(true);
/*Create a new HttpClient and Post Header*/
JSONObject result=null;
HttpClient httpclient = new DefaultHttpClient();
try {
URL url = new URL(cons.PROTOCOL,cons.SERVER,cons.PORT,"/user");
HttpPost httppost = new HttpPost(url.toURI());
HttpResponse response =null;
/*Add your data*/
JSONObject j1=new JSONObject();
JSONObject json=new JSONObject();
j1.put("username", "test");
j1.put("email","test#test.com");
j1.put("password","password");
j1.put("first_name","John");
j1.put("last_name","Doe");
json.put("user",j1);
json.put("mobile_number","256774622240");
StringEntity 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);
Log.i("jazz","It's ALIVE!!!!!");
Log.i("jazz",response.getStatusLine().toString());
} catch (ClientProtocolException e) {
/* TODO Auto-generated catch block*/
} catch (IOException e) {
// TODO Auto-generated catch block
} catch (URISyntaxException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return result;
}
If your are building your HttpPostRequest well, and you only want to know how to attach JSON, here you are a possible solution for it:
StringEntity formEntity = new StringEntity(yourJsonObject.toString());
yourPostRequest.setEntity(formEntity);
I hope this helps!
PS:In addition, let me recommend you the use of this component:
https://github.com/matessoftwaresolutions/AndroidHttpRestService
I've used it in an Android app that is connecting to a python server API and it makes http request easier for your Android client.
Okay, so I'm now answering my own question :D
The issue was with the path variable in the URL string.
This is the format of one of the URL constructors based on this document.
URL(String protocol, String host, int port, String file)
Since I am posting the JSON to the /user path, that's the one I insert into the constructor as the directory.
So, my URL was formed like so:
URL url= new URL("http",cons.SERVER,cons.PORT,"/user/");
My mistake in the beginning was using /user instead of /user/
but other than that, the URL structure and connections are all alright.
I have a json parser which is parsing from a url, the app works on WiFi without problems and fast enough but on mobile network it's very slow and most of time not working.
The speed of the mobile network is good enough that whatsapp is working fast, so I don't know if the problem is related to Json parser or http client.
// Async Task to access the web
public String makeHttpRequest(String url, String method,
List<NameValuePair> params) {
HttpParams params1 = new BasicHttpParams();
params1.setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
HttpClient httpclient = new DefaultHttpClient(params1);
HttpPost httppost = new HttpPost(url);
try {
httppost.setEntity(new UrlEncodedFormEntity(params));
HttpResponse response = httpclient.execute(httppost);
jsonResult = inputStreamToString(
response.getEntity().getContent()).toString();
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// return JSON String
return jsonResult;
}
use any third party tools,which have inbuilt features to make your request fast.
AsyncHttpClient :
HTTP requests happen outside the UI thread
Automatic gzip response decoding support for super-fast requests
Retrofit
finally Volley
Volley is an HTTP library that makes networking for Android apps easier and most importantly, faster
You can see this information from developer.android.com-training-volley
I got a valid Json string(at least every onlinevalidator I tried says so) which contains some chinese characters.
The json string is the following:
{"title":"\u8981\u805e--\u83ef\u723e\u8857\u65e5\u5831","url":"http://cn.wsj.com","desc":"\u300a\u83ef\u723e\u8857\u65e5\u5831\u300b\u4e2d\u6587\u7db2\u7d61\u7248\u6700\u65b0\u8ca1\u7d93\u8981\u805e","imageUrl":null,"lastUpdate":"1327588937","items":[{"title":"\u4e16\u8cbf\u7d44\u7e54\u7e3d\u5e79\u4e8b\ufe55\u4eba\u6c11\u5e63\u5e63\u503c\u88ab\u4f4e\u4f30\ufe50\u4f46\u4f4e\u4f30\u7a0b\u5ea6\u4e0d\u660e","desc":"\u4e16\u754c\u8cbf\u6613\u7d44\u7e54\u7e3d\u5e79\u4e8b\u5e15\u65af\u5361\u723e\uff0e\u62c9\u7c73\u9031\u56db\u8868\u793a\ufe50\u4eba\u6c11\u5e63\u532f\u7387\u88ab\u660e\u986f\u4f4e\u4f30\ufe50\u4f46\u4f4e\u4f30\u7a0b\u5ea6\u9084\u4e0d\u6e05\u695a\u3002","url":"http://cn.wsj.com/big5/20120126/BCHc-20120126WR182711424.asp?source=rss","pubdate":null}]}
Now when i Parse the JsonString in Android via new JsonObject(jsonString) I only got some squares instead of characters.
Why cant android handle this json string?
Any help would be apreciated.
If anyone would like to have the server Ressource, it can be found under:
// edit
url removed
public static String test(){
String testResult= "";
try {
HttpGet get = new HttpGet("http://xxxxx");//edit url removed.
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpResponse response = httpclient.execute(get);
String result = EntityUtils.toString(response.getEntity());
JSONObject obj = new JSONObject(result);
if(!obj.isNull("title")){
testResult= obj.getString("title");
Log.d("Test","Test1:"+ testResult);
}
} catch (JSONException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return testResult;//
}
and Then TextView.setText(testResult);
It works for me.
it's Traditional Chinese String:"要聞--華爾街日報"
May be your ROM has no Traditional Chinese font????
When you receive your JSON, you may have to decode the UTF-8 result when you're building your result. Have a look at utf8 decoding. Something similar to this, but with JSON
I have just a curiosity question. I have an HttpPost request in Android that looks something like this:
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(getString(R.string.url));
//This code does not work
HttpParams params = new BasicHttpParams();
params.setParameter("type", "20");
post.setParams(params);
try {
HttpResponse response = client.execute(post);
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
On my server side, I have a servlet that listens for requests and parses the parameters:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Enumeration en = request.getParameterNames();
while (en.hasMoreElements()){
System.out.println(en.nextElement());
}
}
When I execute this code, the servlet does not see any parameters at all. But if I replace the whole "parameter" chunk with this code:
//This code works
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(5);
nameValuePairs.add(new BasicNameValuePair("type", "20"));
try {
post.setEntity(new UrlEncodedFormEntity(nameValuePairs));
} catch (UnsupportedEncodingException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
My servlet can parse parameters. It's not a problem, I'm just going to use the entity but my question is, why can't my servlet getthe parameters from the first code chunk? What's wrong with setParams? Why can the servlet see parameters if I make them an entity?
In HTML when we have something like "http://host/path?user=uname&passwd=pass", we call the part (user=uname&passwd=pass) after the question mark "form data".The "form data" can be attached to the end of the URL after a question mark (as above), for GET requests, or sent to the server on a separate line, for POST requests.The "form data" are split to parameters. The parameters are separated by & when we use GET.
In our case the HttpPost and HttpGet classes extend the AbstractHttpMessage which implements the setParams method. This method is same for GET and POST but does the job only for GET! In the case of GET the parameters are put in the URL. In the case of POST you need to set the entity for the parameters to be on a "separate line".
On the server side when using servlets the getParameters is clever enough to find the parameters for GET and POST.
Thats why on the server side we do not need to change the code for getting the parameters!
Hope I helped!
I am making an app for Android. I like to make the rest calls as quick as possible. When I get my results as XML it takes 5 seconds (!) to get a simple xml like this:
<souvenirs>
<souvenir>
<id>1</id>
<name>Example 1</name>
<rating>3.4</rating>
<photourl>/images/example.jpg</photourl>
<price>3.50</price>
</souvenir>
<souvenir>
<id>2</id>
<name>Example 2</name>
<rating>2.4</rating>
<photourl>/images/example.jpg</photourl>
<price>8.50</price>
</souvenir>
</souvenirs>
So I tried it with JSON. But that takes also about 5 seconds to retrieve.
I load the XML in android with the following code:
URL url = new URL("http://example.nu?method=getAllSouvenirs");
URLConnection conn = url.openConnection();
long t=System.currentTimeMillis();
InputStream ins = conn.getInputStream();
Log.d("info", String.valueOf((System.currentTimeMillis()-t)));
The log says it takes about 5000 ms to get the inputstream.. Is there any way to speed this up? does anybody knows which technique the Android Market uses? This loads way faster than my app..
Thanks in advance! :)
When you try to get the data "manually" - via browser or via other means (wget, curl) how long does it take there.
On Android you also should take the mobile network into consideration that is usually significantly slower than for a desktop computer. Also latencies are bigger.
To me this sounds a lot like issues in the backend (e.g. trying to resolve the IP of the client and thus taking lots of time).
use Apache HttpClient instead of URLConnection:
Apache http client or URLConnection
EDIT(2012-02-07): no longer true on newer android platform please read: http://android-developers.blogspot.com/2011/09/androids-http-clients.html
Maybe that is how it is implemented and you can't do nothing. That is my guess.
My opinion is to do all connection based stuff on your own thread (to put in in background) and in foreground (main UI thread) entertain user. :)
I have played a little bit around this and it works fast enough for me... Here is my code:
private static HttpResponse doPost(String url, JSONStringer json) {
try {
HttpPost request = new HttpPost(url);
StringEntity entity;
entity = new StringEntity(json.toString());
entity.setContentType("application/json;charset=UTF-8");
entity.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, "application/json;charset=UTF-8"));
request.setEntity(entity);
try {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpResponse response = httpClient.execute(request);
return response;
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
And somewhere else I call that method like:
HttpResponse httpResponse = doPost(url, json);
BufferedReader reader = new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent(), "UTF-8"));
It works fine for me...