Sending images using Http Post
Asked Answered
B

5

134

I want to send an image from the android client to the Django server using Http Post. The image is chosen from the gallery. At present, I am using list value name Pairs to send the necessary data to the server and receiving responses from Django in JSON. Can the same approach be used for images (with urls for images embedded in JSON responses)?

Also, which is a better method: accessing images remotely without downloading them from the server or downloading and storing them in a Bitmap array and using them locally? The images are few in number (<10) and small in size (50*50 dip).

Any tutorial to tackle these problems would be much appreciated.

Edit: The images chosen from the gallery are sent to the server after scaling it to required size.

Bushwa answered 29/5, 2010 at 17:19 Comment(0)
Y
146

I'm going to assume that you know the path and filename of the image that you want to upload. Add this string to your NameValuePair using image as the key-name.

Sending images can be done using the HttpComponents libraries. Download the latest HttpClient (currently 4.0.1) binary with dependencies package and copy apache-mime4j-0.6.jar and httpmime-4.0.1.jar to your project and add them to your Java build path.

You will need to add the following imports to your class.

import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;

Now you can create a MultipartEntity to attach an image to your POST request. The following code shows an example of how to do this:

public void post(String url, List<NameValuePair> nameValuePairs) {
    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("image")) {
                // If the key equals to "image", 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);
    } catch (IOException e) {
        e.printStackTrace();
    }
}
Younts answered 30/5, 2010 at 0:55 Comment(19)
As I mentioned earlier, the images I am sending are small in size. So do I need to use MultiPartEntity to send them?Bushwa
I would most definitely recommend this. This way you probably can use Django features to receive the image and store it easily. One other way would be to encode the byte stream from the image to a base64 encoded string and decode it server side. But this would be too much of a hassle in my opinion and not the way to go.Younts
The images chosen from the gallery are sent to the server after scaling it to 50*50 dip. So I don't have a path to add to list value name pairs. So only the second approach you mentioned seems possible.Bushwa
You could save the image to a temporary file or if you want to skip all this you could take a look at androidcodemonkey.blogspot.com/2010/03/…. This describes how to use Base64 encode. You can just use that as a string and skip my MultipartEntity example.Younts
I am sending the images using this approach only i.e Filebody but it gives OutOfMemory Exception while uploading images. Is there any way we can handle that.Milburt
Hey guys, is there any way to do this without MultipartEntity? I REALLY don't want to import all of Apache HC just for those 4 classes. :-(Promisee
Not at the moment as far as I know. You could go with the base64 encoding and just post that as string data to your server and decode it on the backend. That way you don't need to import the .jar's.Younts
To send image we can covert it to byte array, then create new ByteArrayBody (see Interface ContentBody) and add it to multi-part entity. See my post.Dunstable
For FileBody the Content-Type always seems to be application/octet-stream although I would need it to be image/jpeg. Any suggestions on how I could solve that?Virtual
Just add a 2nd parameter to FileBody with your desired Mime Type. E.g.: new FileBody(new File (nameValuePairs.get(index).getValue()), "image/jpeg")Younts
It looks like multipartentity is deprecated?Lightless
i cannot find apache-mime in the download link? is it not needed?Aggregation
@IllegalArgument Seems it's coupled in httpmime-4.3.2.jar right now. So I guess you indeed don't need it anymore. Let me know if this is the case and I'll update the answer. Thanks for the heads up!Younts
@Younts I was thinking about editing your answer too. Multipart entity is depreciated along with the string body version that you are using. The reason I am not editing is because i couldnot bind all data in namevaluepairs as you have done.Aggregation
@IllegalArgument Alright, I'll look into it and see what has been changed. Thanks!Younts
MultipartEntity deprecated use MultipartEntityBuilder.Monofilament
its giving filenotfoundexception .. please tell me how to pass the sdcard imageMargie
hi any one can provide some help i need to upload both profile image file and basic details to server using post methode please help meOutline
@Outline just pass those details in as nameValuePairs. Only the one named 'image' will be treated as a file. Also, A THOUSAND TIMES UPVOTED!!!Aminoplast
J
15

Version 4.3.5 Updated Code

  • httpclient-4.3.5.jar
  • httpcore-4.3.2.jar
  • httpmime-4.3.5.jar

Since MultipartEntity has been deprecated. Please see the code below.

String responseBody = "failure";
HttpClient client = new DefaultHttpClient();
client.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);

String url = WWPApi.URL_USERS;
Map<String, String> map = new HashMap<String, String>();
map.put("user_id", String.valueOf(userId));
map.put("action", "update");
url = addQueryParams(map, url);

HttpPost post = new HttpPost(url);
post.addHeader("Accept", "application/json");

MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setCharset(MIME.UTF8_CHARSET);

if (career != null)
    builder.addTextBody("career", career, ContentType.create("text/plain", MIME.UTF8_CHARSET));
if (gender != null)
    builder.addTextBody("gender", gender, ContentType.create("text/plain", MIME.UTF8_CHARSET));
if (username != null)
    builder.addTextBody("username", username, ContentType.create("text/plain", MIME.UTF8_CHARSET));
if (email != null)
    builder.addTextBody("email", email, ContentType.create("text/plain", MIME.UTF8_CHARSET));
if (password != null)
    builder.addTextBody("password", password, ContentType.create("text/plain", MIME.UTF8_CHARSET));
if (country != null)
    builder.addTextBody("country", country, ContentType.create("text/plain", MIME.UTF8_CHARSET));
if (file != null)
    builder.addBinaryBody("Filedata", file, ContentType.MULTIPART_FORM_DATA, file.getName());

post.setEntity(builder.build());

try {
    responseBody = EntityUtils.toString(client.execute(post).getEntity(), "UTF-8");
//  System.out.println("Response from Server ==> " + responseBody);

    JSONObject object = new JSONObject(responseBody);
    Boolean success = object.optBoolean("success");
    String message = object.optString("error");

    if (!success) {
        responseBody = message;
    } else {
        responseBody = "success";
    }

} catch (Exception e) {
    e.printStackTrace();
} finally {
    client.getConnectionManager().shutdown();
}
Jillianjillie answered 3/9, 2014 at 9:4 Comment(3)
Which jar packages is needed?Cruce
httpclient-4.3.5.jar httpcore-4.3.2.jar httpmime-4.3.5.jarJillianjillie
What does addQueryParams return ?Eloiseloisa
B
11

The loopj library can be used straight-forward for this purpose:

SyncHttpClient client = new SyncHttpClient();
RequestParams params = new RequestParams();
params.put("text", "some string");
params.put("image", new File(imagePath));

client.post("http://example.com", params, new TextHttpResponseHandler() {
  @Override
  public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) {
    // error handling
  }

  @Override
  public void onSuccess(int statusCode, Header[] headers, String responseString) {
    // success
  }
});

http://loopj.com/

Broadloom answered 17/2, 2015 at 19:9 Comment(0)
U
5

I struggled a lot trying to implement posting a image from Android client to servlet using httpclient-4.3.5.jar, httpcore-4.3.2.jar, httpmime-4.3.5.jar. I always got a runtime error. I found out that basically you cannot use these jars with Android as Google is using older version of HttpClient in Android. The explanation is here http://hc.apache.org/httpcomponents-client-4.3.x/android-port.html. You need to get the httpclientandroidlib-1.2.1 jar from android http-client library. Then change your imports from or.apache.http.client to ch.boye.httpclientandroidlib. Hope this helps.

Ulrike answered 21/6, 2015 at 15:22 Comment(0)
A
-14

I usually do this in the thread handling the json response:

try {
  Bitmap bitmap = BitmapFactory.decodeStream((InputStream)new URL(imageUrl).getContent());
} catch (MalformedURLException e) {
  e.printStackTrace();
} catch (IOException e) {
  e.printStackTrace();
}

If you need to do transformations on the image, you'll want to create a Drawable instead of a Bitmap.

Adrianadriana answered 29/5, 2010 at 19:49 Comment(1)
The question is how to post an image, and not how to get it.Dandelion

© 2022 - 2024 — McMap. All rights reserved.