I have code to send text and multiple image in one request to server, my case is, I loop through local db to get the data and multiple image so I can use addPart(key, textdata); for the text data and addPart(key, filename, inputstream, "application/octet-stream"); for the image data. But the problem is when I have more than one image in one request I only able to send one of them. Here are my complete code. The main problem happens on line 31 when I have more than one image it only send one of them. I will appreciate any help. Thank you.
The problem I think is might be here
reqEntity.addPart("myFile", yourImage);
In this your key(myFile) remains the same for all the images. so when your images are more than one, it keeps on overwriting the previous image. So I think, you should attach index with your key(starting from 0,1 and so on), something like this for example
reqEntity.addPart("myFile_"+i, yourImage);
And also send the image_count to server along with images,so that, it will get to know how many images you are actually sending and by having a simple for loop at the server end,they will be able to get all these images. hope this helps.
Try this way
String sResponse = "";
String url = "http://www.api.in/rpcs/uploadfiles/?";
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
MultipartEntity entity = new MultipartEntity();
options1.inPreferredConfig = Bitmap.Config.ARGB_8888;
byte[] data1 = null,data2= null,data3= null,data4= null,data5= null;
if(PreferenceManager.getDefaultSharedPreferences(getBaseContext()).contains("endum_image_0"))
{ up_image1 = PreferenceManager.getDefaultSharedPreferences(getBaseContext()).getString("endum_image_0", "");
bitmap = BitmapFactory.decodeFile(up_image1, options1);
bitmap.compress(CompressFormat.JPEG, 100, bos1);
data1 = bos1.toByteArray();
}
if(PreferenceManager.getDefaultSharedPreferences(getBaseContext()).contains("endum_image_1"))
{ up_image2 = PreferenceManager.getDefaultSharedPreferences(getBaseContext()).getString("endum_image_1", "");
bitmap = BitmapFactory.decodeFile(up_image2, options1);
bitmap.compress(CompressFormat.JPEG, 100, bos2);
data2 = bos2.toByteArray();
}
if(PreferenceManager.getDefaultSharedPreferences(getBaseContext()).contains("endum_image_2"))
{ up_image3 = PreferenceManager.getDefaultSharedPreferences(getBaseContext()).getString("endum_image_2", "");
bitmap = BitmapFactory.decodeFile(up_image3, options1);
bitmap.compress(CompressFormat.JPEG, 100, bos3);
data3 = bos3.toByteArray();
}
if(PreferenceManager.getDefaultSharedPreferences(getBaseContext()).contains("endum_image_3"))
{ up_image4 = PreferenceManager.getDefaultSharedPreferences(getBaseContext()).getString("endum_image_3", "");
bitmap = BitmapFactory.decodeFile(up_image4, options1);
bitmap.compress(CompressFormat.JPEG, 100, bos4);
data4 = bos4.toByteArray();
}
if(PreferenceManager.getDefaultSharedPreferences(getBaseContext()).contains("endum_image_4"))
{ up_image5 = PreferenceManager.getDefaultSharedPreferences(getBaseContext()).getString("endum_image_4", "");
bitmap = BitmapFactory.decodeFile(up_image5, options1);
bitmap.compress(CompressFormat.JPEG, 100, bos5);
data5 = bos5.toByteArray();
}
entity.addPart("post_id", new StringBody(post_id));
entity.addPart("user_id", new StringBody(user_id));
entity.addPart("cat_id", new StringBody(category));
if(data1!=null){
entity.addPart("files[]", new ByteArrayBody(data1,"image/jpeg", "u1.jpg"));
}
if(data2!=null){
entity.addPart("files[]", new ByteArrayBody(data2,"image/jpeg", "u2.jpg"));
}
if(data3!=null){
entity.addPart("files[]", new ByteArrayBody(data3,"image/jpeg", "u3.jpg"));
}
if(data4!=null){
entity.addPart("files[]", new ByteArrayBody(data4,"image/jpeg", "u4.jpg"));
}
if(data5!=null){
entity.addPart("files[]", new ByteArrayBody(data5,"image/jpeg", "u5.jpg"));
}
httpPost.setEntity(entity);
HttpResponse response = httpClient.execute(httpPost);
BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
StringBuilder s = new StringBuilder();
while ((sResponse = reader.readLine()) != null)
{
s = s.append(sResponse);
}
if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK)
{
return s.toString();
}else
{
return "{\"status\":\"false\",\"message\":\"Some error occurred\"}";
}
Related
I am using HttpClient 4.3.6 to perform http GET and POST requests. Right now I am using multipartentity to send a few string parameters and an image in the form of a file. I am able to successfully post the data but my problem comes in when I get the HTTP response. The response contains json data.
What happens is the HTTP response is incomplete and when i try to create a json object with the data i get jsonexception error saying:
Unterminated object at character 407.
I noticed that the response does not contain closed braces. Is this a problem on android or should I check the server? Because I am able to see the data properly on postman and on ios. I have never faced this issue before and don't know how to solve this.
This is my code to post and get the response:
#Override
protected String doInBackground(String... params) {
try {
String url = params[0];
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(url);
MultipartEntity entity = new MultipartEntity();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] imageBytes = baos.toByteArray();
ByteArrayBody bab = new ByteArrayBody(imageBytes, "image.jpg");
entity.addPart("image_data", bab);
entity.addPart("action", new StringBody("1", "text/plain", Charset.forName("UTF-8")));
entity.addPart("name", new StringBody("asdfg", "text/plain", Charset.forName("UTF-8")));
entity.addPart("user_id", new StringBody("157", "text/plain", Charset.forName("UTF-8")));
entity.addPart("birthday", new StringBody("18-04-1995", "text/plain", Charset.forName("UTF-8")));
entity.addPart("gender", new StringBody("male", "text/plain", Charset.forName("UTF-8")));
entity.addPart("is_jlpt_student", new StringBody(String.valueOf(0), "text/plain", Charset.forName("UTF-8")));
entity.addPart("relationship", new StringBody("Father", "text/plain", Charset.forName("UTF-8")));
entity.addPart("relationship_id", new StringBody(String.valueOf(10002), "text/plain", Charset.forName("UTF-8")));
entity.addPart("is_creator", new StringBody(String.valueOf(1), "text/plain", Charset.forName("UTF-8")));
entity.addPart("email", new StringBody(email, "text/plain", Charset.forName("UTF-8")));
httppost.setEntity(entity);
HttpResponse resp = httpclient.execute(httppost);
String response = EntityUtils.toString(resp.getEntity());
Log.i("HttpResponse", response);
return response;
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute (String result) {
super.onPostExecute(result);
JSONObject jsonObject = null;
try {
jsonObject = new JSONObject(result);
JSONObject json_data = jsonObject.getJSONObject("data");
String json_userid = json_data.getString("user_id");
String json_username = json_data.getString("name");
String json_email = json_data.getString("email");
String json_country = json_data.getString("country_code");
String json_imagefilename = json_data.getString("image_filename");
String json_imgurl = json_data.getString("image_url");
Toast.makeText(ParentGuardianProfile.this, "ImageFile " + json_imagefilename, Toast.LENGTH_SHORT).show();
User new_user = userdao.createUser(json_userid, json_username, json_email,json_imagefilename,json_country,selectedImageUri.toString(), 1);
Log.i("SQLITE", "added user : " + new_user.getmUserName() + new_user.getmId());
} catch (JSONException e) {
e.printStackTrace();
}
}
And my json response is :
{"status":1,"message":"success","data":{"child_id":"381","name":"asdfg","image_filename":"C201603021734476.jpg","image_url":"https:\/\/innokid.blob.core.windows.net\/media\/child\/381.jpg","birthday":"18-04-1995","gender":"male","is_jltp_student":"0","relationship":"Father","relationship_id":"10002","is_creator":1,"rank":1,"qrcode_url":"http:\/\/innokid.azurewebsites.net\/uploads\/qrcode\/child_381.png"
I tried using String buffer as suggested in this post String is being truncated when its too long . But i still get the same result.
Code looks ok at first glance.
How do you got know that the json data is cut? Logcat can truncate text. Debugger should be more reliable in this case.
Try to generate this same request with some tools like curl / SoapUI and validate JSON you got with some formatter / validator (you'll easily find a few of such tools).
It's beyond the range of question, but using raw Android built-in communication libraries seems to be a little bit masochistic. Have you ever consider to use Retrofit?
I think this code is problematic String response = EntityUtils.toString(resp.getEntity());
may be you should use some other function to convert response toString...
Apparently the json is missing two curly brackets '}}' at the end, which can happen due to some bug in the toString code.
I pulled up an old project that was using the org.apache.http stuff and below is how I was parsing the response. As you can see it is rather cumbersome. There are many tested and maintained libraries out there that are better suited to this kind of heavy-lifting.
// Get hold of the response entity (-> the data):
HttpEntity entity = response.getEntity();
if (entity != null) {
// Read the content stream
InputStream instream = entity.getContent();
Header contentEncoding = response.getFirstHeader("Content-Encoding");
if (contentEncoding != null && contentEncoding.getValue().equalsIgnoreCase("gzip")) {
instream = new GZIPInputStream(instream);
}
// Convert content stream to a String
resultString = convertStreamToString(instream);
instream.close();
// Do stuff with resultString here
// Consume Content
entity.consumeContent();
}
And the convertStreamToString() method:
private static String convertStreamToString(InputStream is) {
/*
* To convert the InputStream to String we use the
* BufferedReader.readLine() method. We iterate until the BufferedReader
* return null which means there's no more data to read. Each line will
* appended to a StringBuilder and returned as String.
*
* (c) public domain:
* http://senior.ceng.metu.edu.tr/2009/praeda/2009/01/
* 11/a-simple-restful-client-at-android/
*/
BufferedReader reader = new BufferedReader(new InputStreamReader(is), 8192);
StringBuilder sb = new StringBuilder();
String line = null;
try {
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return sb.toString();
}
I finally solved this issue by replacing httpclient library with Android Asynchronous Http Client. Now it works fine. Thanks a lot for your help!
However, I still dont understand why the response was truncated when i used httpclient.
Hi I am making an app which sends picture to a server. The version with the Apache deprecated functions work, but I don't know why I can't get the updated solution to work. Anybody knows where is the error here?
Newest solution : it does not give errors in the logcat but when I go to the server nothing has been uploaded. At first I thought that the error was in how I passed the arguments, but I have tried several different solutions like using Uri.builder, methods which encoded the params using a HashMap and an stringBuilder, passing the string like this... and NOTHING worked. I need help this is really driving me crazy
#Override
protected Void doInBackground(Void... params) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream);
String encodedImage = Base64.encodeToString(byteArrayOutputStream.toByteArray(), Base64.DEFAULT);
try {
byteArrayOutputStream.flush();
byteArrayOutputStream.close();
}catch (IOException e){
}
HttpURLConnection connection;
try {
String urlSt = "http://phoenixcoding.tk/SavePicture.php";
URL url = new URL(urlSt);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
/*Uri.Builder builder = new Uri.Builder()
.appendQueryParameter("name", name)
.appendQueryParameter("image", encodedImage);
String query = builder.build().getEncodedQuery();*/
OutputStream os = connection.getOutputStream();
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(os, "UTF-8"));
writer.write("name=example&image=" + encodedImage);
writer.flush();
writer.close();
os.close();
connection.connect();
}catch (IOException e){
e.printStackTrace();
}
return null;
}
Former solution: it works nicely
#Override
protected Void doInBackground(Void... params) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream);
String encodedImage = Base64.encodeToString(byteArrayOutputStream.toByteArray(), Base64.DEFAULT);
try {
byteArrayOutputStream.flush();
byteArrayOutputStream.close();
}catch (IOException e){
}ArrayList<NameValuePair> dataToSend = new ArrayList<NameValuePair>();
dataToSend.add(new BasicNameValuePair("name", name));
dataToSend.add(new BasicNameValuePair("image", encodedImage));
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost("http://phoenixcoding.tk/SavePicture.php");
try{
post.setEntity(new UrlEncodedFormEntity(dataToSend));
client.execute(post);
}catch (Exception e){
e.printStackTrace();
}
return null;
}
The SavePhoto.php file:
<?php
$name = $_POST["name"];
$image = $_POST["image"];
$decodedImage = base64_decode("$image");
file_put_contents("pictures/" . $name . ".JPG", $decodedImage);
?>
Try this in your php code:
if( isset($_POST["image"]) && !empty($_POST["image"])){
$profile_pic = '';
$data= $_POST['image'];
$data = str_replace('data:image/png;base64,', '', $data);
$data = str_replace(' ', '+', $data);
$binary=base64_decode($data);
header('Content-Type: bitmap; charset=utf-8');
// Images will be saved under 'www/pictures' folder
$new_name = $_POST['name'] . '.png';
$success =file_put_contents('pictures/'.$new_name,$binary);
$profile_pic = $new_name;
}
i guess this line is buggy :- $decodedImage = base64_decode("$image"); u must write like this instead $decodedImage = base64_decode($image);
to debug do this :-
<?php
file_put_contents("post.txt",print_r($_POST,true));
$name = $_POST["name"];
.....
?>
view that as :- http://phoenixcoding.tk/post.txt
( if the file is not saved then there is permission issue in that case make a directory "test" and give it permission 755 even if it does not work make that directory as 777 and then you url will be http://phoenixcoding.tk/test/post.txt )
What you will do is collect all incoming $_POST in file then you will know what post data is coming this will clarify where the error is , on android side or php side if post is okay then android code is okay and issue is in php code.
i hope it will help you fixing the issue...
thanks
Thanks all for your answers, I finally made it work. I have no idea why is this, but after adding an InputStream object after opening the connection, the pictures uploaded correctly. All I did was add these lines:
InputStream is = connection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is, "iso-8859-1"), 8);
StringBuilder str = new StringBuilder();
String strLine;
while ((strLine = reader.readLine()) != null) {
str.append(strLine + "\n");
}
is.close();
I am having a doubt on how can I post a data where my REST end point URL is like below:
http://my.domain.com/Upload/{ID}/{IMAGE_CONTENT_AS_BYTE_ARRAY}
I need to send the the Image content as byte array string to this end point method. But Since the charater length can go beyond 2000 character length, I may not be able to send the the IMAGE if its huge since everything goes as part of URL string. How can I put the data of IMAGE_CONTENT_AS_BYTE_ARRAY .
Also I don't have any key for this so that I can put it in namevalue pair.Please suggest!
Try this code:
MultipartEntityBuilder multipartEntity;
String URL = "My server url";
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
bitmap.compress(CompressFormat.JPEG, 75, byteArrayOutputStream);
byte[] byteData = byteArrayOutputStream.toByteArray();
ByteArrayBody byteArrayBody = new ByteArrayBody(byteData, "image"); // second parameter is the name of the image )
// send the package
multipartEntity = MultipartEntityBuilder.create();
multipartEntity.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
multipartEntity.addPart("image", byteArrayBody);
The best way to upload images or files is using multi part data format.
Here is a sample code for uploading image.
public static void postMultiPart(String url, File image)
{
final android.net.http.AndroidHttpClient client = android.net.http.AndroidHttpClient.newInstance("sample");
// enable redirects
HttpClientParams.setRedirecting(client.getParams(), true);
final String encoded_url = encodeURL(url);
final org.apache.http.client.methods.HttpPost post = new org.apache.http.client.methods.HttpPost(encoded_url);
MultipartEntity mpEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
mpEntity.addPart("profile", new FileBody(image));
post.setEntity(mpEntity);
org.apache.http.HttpResponse response;
try {
response = client.execute(post);
final int statusCode = response.getStatusLine().getStatusCode();
if (!(statusCode == org.apache.http.HttpStatus.SC_OK || statusCode == org.apache.http.HttpStatus.SC_CREATED)) {
Log.i("Error:","Check....."+"Error " + statusCode + " while posting data to " + encoded_url + "\nreason phrase: " + response.getStatusLine().getReasonPhrase());
return;
}
Log.i("SUCCESS:","Check....."+Base64.encodeToString(md.digest(), Base64.DEFAULT));
} catch (IOException e) {
} finally {
client.close();
}
}
Below is the method which I have used to read a response from server by passing a url which retrieved a json object.
There is a very peculiar issue which is still old values has been fetched , though the data has already been updated.
I tried to find out the solution of it but still no success.
Url is of type: http://www.mywebsite.com/svc/user_auth/user_id
Where a user id is the unique integer id of the user which is being passed as a parameter.
public static String getResponse(String url){
String downloadedData = null;
Log.e("getResponse", url);
try {
URL downloadURL = new URL(url);
InputStream inputStream = (InputStream) downloadURL.getContent();
if (null != inputStream) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[512];
int readCounter = inputStream.read(buffer);
while (readCounter != -1) {
byteArrayOutputStream.write(buffer, 0, readCounter);
readCounter = inputStream.read(buffer);
}
downloadedData = new String(
byteArrayOutputStream.toByteArray());
/*if (null != downloadedData && !"".equals(downloadedData)) {
downloadedJson = new JSONObject(downloadedData);
}*/
}else{
Log.e("getResponse", "Response is null");
}
} catch (Exception e) {
e.printStackTrace();
}
return downloadedData;
}
Any help would be appreciated.
Don't know how is URL.getContent() implemented internally. You can try to use URLConnection, it allows you to control whether to use cache by setUseCaches().
Have you tried opening the url from your browser to see the JSON response? If you see the old value in the browser then the problem is on your server side.
If this is not the case try using the DefaultHttpClient for post and get requests like: (maybe some caching occur with the method you are using, this is not the case for sure with HttpClient)
DefaultHttpClient httpclient = getHttpClient();
HttpPost httpost = new HttpPost(url);
httpost.setEntity(entity); //entity has your params wrapped if you have any...this is just an example for POST request, but for your case you can use GET with URL params..
httpclient.execute(httpost);
I make a GET request to a server using HttpUrlConnection.
After connecting:
I get response code: 200
I get response message: OK
I get input stream, no exception thrown but:
in a standalone program I get the body of the response, as expected:
{"name":"my name","birthday":"01/01/1970","id":"100002215110084"}
in a android activity, the stream is empty (available() == 0), and thus I can't get
any text out.
Any hint or trail to follow? Thanks.
EDIT: here it is the code
Please note: I use import java.net.HttpURLConnection; This is the standard
http Java library. I don't want to use any other external library. In fact
I did have problems in android using the library httpclient from apache (some of their anonymous .class can't be used by the apk compiler).
Well, the code:
URLConnection theConnection;
theConnection = new URL("www.example.com?query=value").openConnection();
theConnection.setRequestProperty("Accept-Charset", "UTF-8");
HttpURLConnection httpConn = (HttpURLConnection) theConnection;
int responseCode = httpConn.getResponseCode();
String responseMessage = httpConn.getResponseMessage();
InputStream is = null;
if (responseCode >= 400) {
is = httpConn.getErrorStream();
} else {
is = httpConn.getInputStream();
}
String resp = responseCode + "\n" + responseMessage + "\n>" + Util.streamToString(is) + "<\n";
return resp;
I see:
200
OK
the body of the response
but only
200
OK
in android
Trying the code of Tomislav I've got the answer.
My function streamToString() used .available() to sense if there is any data received,
and it returns 0 in Android. Surely, I called it too soon.
If I rather use readLine():
class Util {
public static String streamToString(InputStream is) throws IOException {
StringBuilder sb = new StringBuilder();
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
String line;
while ((line = rd.readLine()) != null) {
sb.append(line);
}
return sb.toString();
}
}
then, it waits for the data to arrive.
Thanks.
You can try with this code that will return response in String:
public String ReadHttpResponse(String url){
StringBuilder sb= new StringBuilder();
HttpClient client= new DefaultHttpClient();
HttpGet httpget = new HttpGet(url);
try {
HttpResponse response = client.execute(httpget);
StatusLine sl = response.getStatusLine();
int sc = sl.getStatusCode();
if (sc==200)
{
HttpEntity ent = response.getEntity();
InputStream inpst = ent.getContent();
BufferedReader rd= new BufferedReader(new InputStreamReader(inpst));
String line;
while ((line=rd.readLine())!=null)
{
sb.append(line);
}
}
else
{
Log.e("log_tag","I didn't get the response!");
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return sb.toString();
}
The Stream data may not be ready, so you should check in a loop that the data in the stream is available before attempting to access it.
Once the data is ready, you should read it and store in another place like a byte array; a binary stream object is a nice choice to read data as a byte array. The reason that a byte array is a better choice is because the data may be binary data like an image file, etc.
InputStream is = httpConnection.getInputStream();
byte[] bytes = null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] temp = new byte[is.available()];
while (is.read(temp, 0, temp.length) != -1) {
baos.write(temp);
temp = new byte[is.available()];
}
bytes = baos.toByteArray();
In the above code, bytes is the response as byte array. You can convert it to string if it is text data, for example data as utf-8 encoded text:
String text = new String(bytes, Charset.forName("utf-8"));