Gaurav Sarma
Gaurav Sarma

Reputation: 2297

How to post multi-part/form images with string parameter in android

I have an API which has a payload body of type String. But has both json and image (multiparty/form) as part of the payload body. Something like this:

json={jsonbody} image=@images/testing.png

This is what i am doing currently

public static String uploadImageQuery(Context context, String urlString, String method,
                                      JSONObject jsonObject, Bitmap largeImageBitmap,
                                      Dialog dialog) throws IOException {

    String responseString = null;
    HttpURLConnection conn = null;
    URL url = new URL(urlString);

    conn = (HttpURLConnection) url.openConnection();

    Log.d(TAG, "Uploading largeImageBitmap ..");

    conn.setConnectTimeout((int) Constants.THREE_MINUTES);
    conn.setDoOutput(true);
    conn.setDoInput(true);
    conn.setUseCaches(false);
    conn.setRequestMethod(method);
    conn.setChunkedStreamingMode(16 * 1024);
    conn.setRequestProperty("Transfer-Encoding", "chunked");

    // The “boundry” can be any string. In this example it’s **********.
    // It’s used in the body of the request to seperate each field being submitted.
    //conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);
    conn.setRequestProperty("Authorization", "Bearer " + access_token);
    conn.connect();


    DataOutputStream dataOS = new DataOutputStream(conn.getOutputStream());
    dataOS.write(("json=" + jsonObject.toString()).getBytes(Constants.CHARSET_UTF_8));
    dataOS.write(("image=").getBytes(Constants.CHARSET_UTF_8));

    /* Standard order patten for sending multipart data*/
    dataOS.write(buildStartPayload().getBytes(Constants.CHARSET_UTF_8));
    dataOS.write(getImageBytes(largeImageBitmap));
    dataOS.write(buildEndPayload().getBytes(Constants.CHARSET_UTF_8));

    Log.d(TAG, "Posting String data to server : " + dataOS.toString());

    dataOS.flush();
    dataOS.close();

    // Ensure we got the HTTP 200 response code
    int responseCode = conn.getResponseCode();
    String responseMessage = conn.getResponseMessage();
    Log.d(TAG, "Response code for upload image query : " + responseCode + " Message : " + responseMessage);

    if (responseCode != 200) {
        dialog.cancel();
        Log.e(TAG, String.format("Received the response code %d from the URL %s", responseCode, url));
        // DisplayMessage.error("Couldn't upload image. Please try again later.", activity);
    }

    // Read the response
    InputStream is = conn.getInputStream();
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    byte[] bytes = new byte[1024];
    int bytesRead;
    while ((bytesRead = is.read(bytes)) != -1) {
        baos.write(bytes, 0, bytesRead);
    }
    byte[] bytesReceived = baos.toByteArray();
    baos.close();
    is.close();

    String response = new String(bytesReceived);
    Log.d(TAG, "Response:" + response);

    conn.disconnect();
    conn = null;
    Log.d(TAG, "Cleard the connection handle.");

    return responseString;
}

private static String buildStartPayload() {
    String contentDisposition = "Content-Disposition: form-data; name=\"testing\"; filename=\"testing.png\"";
    String contentType = "Content-Type: image/png";

    // This is the standard format for a multipart request
    StringBuilder requestBody = new StringBuilder();
    requestBody.append(LINE_START);
    requestBody.append(BOUNDARY);
    requestBody.append(LINE_END);
    requestBody.append(contentDisposition);
    requestBody.append(LINE_END);
    requestBody.append(contentType);
    requestBody.append(LINE_END);
    requestBody.append(LINE_END);
    return requestBody.toString();
}

private static String buildEndPayload() {
    // This is the standard format for a multipart request
    StringBuilder requestBody = new StringBuilder();
    requestBody.append(LINE_END + LINE_START + BOUNDARY + LINE_START + LINE_END);
    return requestBody.toString();
}

I have used HttpURLConnection before to post a multipart/form image and tried doing it using DataOutputform but I am getting a "Bad request" error. Is there library that can help? I use volley primary but it doesn't have good image support. I have not tried Retrofit but don't want to go there right now. I am hopeful this can be done using HttpURLConnection.

Upvotes: 0

Views: 1088

Answers (2)

Rajesh Satvara
Rajesh Satvara

Reputation: 3964

you can use this library link is click here..

compile "cz.msebera.android:httpclient:4.4.1.2"

code for add image

protected String doInBackground(Void... params) {
            String result = "";
            try {
                HttpClient client = new DefaultHttpClient();
                HttpPost post = new HttpPost("your url");
                post.setHeader("key", Key_for_XYZ);

                MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create();
                entityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
                entityBuilder.addTextBody("id", id);
                entityBuilder.addTextBody("name", fnm);
                // file path.....
                entityBuilder.addBinaryBody("uploaded_file", destination);

                cz.msebera.android.httpclient.HttpEntity entity = entityBuilder.build();
                post.setEntity(entity);
                cz.msebera.android.httpclient.HttpResponse response = client.execute(post);
                cz.msebera.android.httpclient.HttpEntity httpEntity = response.getEntity();
                result = EntityUtils.toString(httpEntity);
                Log.e("result", result);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return result;
        }

// make sure you had import this packages...

import cz.msebera.android.httpclient.client.HttpClient;
import cz.msebera.android.httpclient.client.methods.HttpPost;
import cz.msebera.android.httpclient.entity.mime.HttpMultipartMode;
import cz.msebera.android.httpclient.entity.mime.MultipartEntityBuilder;
import cz.msebera.android.httpclient.impl.client.DefaultHttpClient;
import cz.msebera.android.httpclient.util.EntityUtils;

Upvotes: 0

Fndroid
Fndroid

Reputation: 465

You might need to encode the image to a String, then put that String into your request body.

If you are using volley, you can try this:

    StringRequest stringRequest = new StringRequest(Request.Method.POST, URL, new Response
            .Listener<String>() {
        @Override
        public void onResponse(String response) {
            Log.d(TAG, "onResponse() called with: response = [" + response + "]");
        }
    }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            Log.d(TAG, "onErrorResponse() called with: error = [" + error + "]");
        }
    }) {
        @Override
        protected Map<String, String> getParams() throws AuthFailureError {
            Map<String, String> params = new HashMap<>();
            params.put("img", BASE64_IMG);
            return params;
        }
    };
    mRequestQueue.add(stringRequest);

Override getParams and put your params in your request.

You have to encode your image to a String, using Base64.

Upvotes: 0

Related Questions