9

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)?

reiley
  • 3,759
  • 12
  • 58
  • 114

4 Answers4

5

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

Jee Mok
  • 6,157
  • 8
  • 47
  • 80
2

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

fida1989
  • 3,234
  • 1
  • 27
  • 30
  • Few queries..Are you using NameValuePair of package `(org.apache.http.NameValuePair)`... & What is the return type of `Constants.all_datas.get(pos).getImage()`, is it `String`. If yes then have to converted `byte[]` to `String`? – reiley Apr 07 '14 at 09:13
  • 1
    NameValuePair is from apache mime4j library and the getImage() method returns the path of image in device. – fida1989 Apr 07 '14 at 09:38
  • What if I need to send multiple images in single request. Like {id:"1", images:image1, image2} ? – reiley Apr 07 '14 at 11:11
  • add another namevaluepair with the "uploadedfile" tag. – fida1989 Apr 07 '14 at 11:13
2

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;
}
Francesco verheye
  • 1,574
  • 2
  • 14
  • 32
-1

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 SDKAndroidObject
Boris Strandjev
  • 46,145
  • 15
  • 108
  • 135
  • 1
    Images can be and are uploaded via JSON and its a standard practice so all above reasons are meaningless – vishal dharankar Feb 08 '15 at 09:33
  • @vishal by 'images are' you mean that the images in Facebook, G+, instagram, soundcloud, twitter load for you immediately with the content, or rather that you have lousy in performance, not-so-popular app where you have personally chosen to put them in the JSON? – Boris Strandjev Feb 08 '15 at 09:43
  • 1
    Read question carefully its about uploading image and not downloading , for fetching image in app it would be link no doubt but for uploading ? – vishal dharankar Feb 08 '15 at 10:28
  • 1
    @vishal I am still not confident that the qeustion is regarding uploading, but even if it would be so I would not go with the overhead of converting the image to text format (say x64), when the client can transmit in raw format. Fruthermore you need to handle network failures and do retries and REST is not meant for such tasks. – Boris Strandjev Feb 08 '15 at 12:10
  • It's about uploading coz the code he is looking for is in Java and answers as well not difficult – vishal dharankar Feb 09 '15 at 09:10