I'm using JSON
with REST
api for using web service.
Now I also need to send Images in request. Is it possible?
If yes, what changes do I need to do on client/server side.
And in my Java code, how should I send the image content (do I need to set a content type separately)?
The way to do that would be to send it as content inside a HttpPost request as below
HttpClient client = new DefaultHttpClient();
HttpPost postRequest = new HttpPost(url);
String body = getMessageBody();
try
{
postRequest.setEntity(new StringEntity(body, "UTF8"));
postRequest.setHeader("Content-Type", "application/x-www-form-urlencoded");
HttpResponse response = client.execute(postRequest);
return response;
} catch (UnsupportedEncodingException e)
{
e.printStackTrace();
} catch (ClientProtocolException e)
{
e.printStackTrace();
} catch (IOException e)
{
e.printStackTrace();
}
The way you would string encode the image would be to do the following.
BufferedImage img = ImageIO.read(new File("filename.jpg"));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(img, "jpg", baos);
baos.flush();
Base64 base = new Base64(false);
String encodedImage = base.encodeToString(baos.toByteArray());
baos.close();
encodedImage = java.net.URLEncoder.encode(encodedImage, "ISO-8859-1");
Good luck
Sample app side code that worked for me. You can send image in one valuepair and the json in another valuepair: (Here "uploadedfile" tag defines the valuepair as the path of the image file in sd card during checking in post function, other tags will be considered as text data)
List<NameValuePair> values; values = new ArrayList<NameValuePair>();
System.out.println(Constants.all_datas.get(pos).getBookName());
values.add(new NameValuePair("uploadedfile",
Constants.book_image_path
+ Constants.all_datas.get(pos).getImage()));
values.add(new NameValuePair("id", Constants.all_datas.get(pos)
.getBookid() + ""));
values.add(new NameValuePair("bookname", Constants.all_datas
.get(pos).getBookName()));
values.add(new NameValuePair("price", Constants.all_datas.get(
pos).getPrice()));
values.add(new NameValuePair("writtername", Constants.all_datas
.get(pos).getWritterName()));
values.add(new NameValuePair("publishername",
Constants.all_datas.get(pos).getPublisherName()));
post(values);
// Post Function
public void post(final List<NameValuePair> nameValuePairs) {
// Setting progressDialog properties
progressDialog = ProgressDialog.show(CustomBookActivity.this, "",
"Syncing Book Data...");
mHandler = new Handler();
// Function to run after thread
mUpdateResults = new Runnable() {
public void run() {
progressDialog.dismiss();
// Something
}
};
new Thread() {
@Override
public void run() {
HttpClient httpClient = new DefaultHttpClient();
HttpContext localContext = new BasicHttpContext();
HttpPost httpPost = new HttpPost(URL);
try {
MultipartEntity entity = new MultipartEntity(
HttpMultipartMode.BROWSER_COMPATIBLE);
for (int index = 0; index < nameValuePairs.size(); index++) {
if (nameValuePairs.get(index).getName()
.equalsIgnoreCase("uploadedfile")) {
// If the key equals to "uploadedfile", we use FileBody
// to transfer the data
entity.addPart(
nameValuePairs.get(index).getName(),
new FileBody(new File(nameValuePairs.get(
index).getValue())));
} else {
// Normal string data
entity.addPart(nameValuePairs.get(index).getName(),
new StringBody(nameValuePairs.get(index)
.getValue()));
}
}
httpPost.setEntity(entity);
HttpResponse response = httpClient.execute(httpPost,
localContext);
HttpEntity result_entity = response.getEntity();
String htmlResponse = EntityUtils.toString(result_entity);
result = htmlResponse;
System.out.println("SYNC:::" + result);
// server = true;
} catch (IOException e) {
e.printStackTrace();
// server = false;
}
// dismiss the progress dialog
// Calling post function
mHandler.post(mUpdateResults);
}
}.start();
}
Apache Mime4J, HTTPCore, HTTPMime libary jars need to be added to project
I use this code in my AsyncTask:
@Override
protected String doInBackground(String... str) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
String encodedImage = bitmapToString(mBitmap);
ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("data", encodedImage));
try {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(
"http://192.168.0.107:8300/upload/upload");
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httppost);
String the_string_response = convertResponseToString(response);
return the_string_response;
} catch (Exception e) {
System.out.println("Error in http connection " + e.toString());
return "error";
}
}
public String bitmapToString(Bitmap bitmap) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] b = baos.toByteArray();
String temp = null;
try {
System.gc();
temp = Base64.encodeToString(b, Base64.DEFAULT);
} catch (Exception e) {
e.printStackTrace();
} catch (OutOfMemoryError e) {
baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 50, baos);
b = baos.toByteArray();
temp = Base64.encodeToString(b, Base64.DEFAULT);
Log.e("PictureDemo", "Out of memory error catched");
}
return temp;
}
private String convertResponseToString(HttpResponse response)
throws IllegalStateException, IOException {
String res = "";
StringBuffer buffer = new StringBuffer();
inputStream = response.getEntity().getContent();
int contentLength = (int) response.getEntity().getContentLength();
if (contentLength < 0) {
} else {
byte[] data = new byte[512];
int len = 0;
try {
while (-1 != (len = inputStream.read(data))) {
buffer.append(new String(data, 0, len));
}
} catch (IOException e) {
e.printStackTrace();
}
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
res = buffer.toString();
}
return res;
}
You should not send the image itself, but url from which it can be downloaded.
Otherwise:
- you make the request too big
- usually you would like to load the images asynchronously, which can only be achieved if the contents are separated from the other data.
- you most probably would not be able to make use of automatic JSON parsing libraries like GSON, Jackson, or the integrated in the Adnroid SDK
AndroidObject