As part of my Android app, I'd like to upload bitmaps to be remotely stored. I have simple HTTP GET and POST communication working perfectly, but documentation on how to do a multipart POST seems to be as rare as unicorns.
Furthermore, I'd like to transmit the image directly from memory, instead of working with a file. In the example code below, I'm getting a byte array from a file to be used later on with HttpClient and MultipartEntity.
File input = new File("climb.jpg");
byte[] data = new byte[(int)input.length()];
FileInputStream fis = new FileInputStream(input);
fis.read(data);
ByteArrayPartSource baps = new ByteArrayPartSource(input.getName(), data);
This all seems fairly clear to me, except that I can't for the life of me find out where to get this ByteArrayPartSource. I have linked to the httpclient and httpmime JAR files, but no dice. I hear that the package structure changed drastically between HttpClient 3.x and 4.x.
Is anyone using this ByteArrayPartSource in Android, and how did they import it?
After digging around in the documentation and scouring the Internet, I came up with something that fit my needs. To make a multipart request such as a form POST, the following code did the trick for me:
File input = new File("climb.jpg");
DefaultHttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost("http://localhost:3000/routes");
MultipartEntity multi = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
String line;
multi.addPart("name", new StringBody("test"));
multi.addPart("grade", new StringBody("test"));
multi.addPart("quality", new StringBody("test"));
multi.addPart("latitude", new StringBody("40.74"));
multi.addPart("longitude", new StringBody("40.74"));
multi.addPart("photo", new FileBody(input));
post.setEntity(multi);
HttpResponse resp = client.execute(post);
The HTTPMultipartMode.BROWSER_COMPATIBLE bit is very important. Thanks to Radomir's blog on this one.
try this:
HttpClient httpClient = new DefaultHttpClient() ;
HttpPost httpPost = new HttpPost("http://example.com");
MultipartEntity entity = new MultipartEntity();
entity.addPart("file", new FileBody(file));
httpPost.setEntity(entity );
HttpResponse response = null;
try {
response = httpClient.execute(httpPost);
} catch (ClientProtocolException e) {
Log.e("ClientProtocolException : "+e, e.getMessage());
} catch (IOException e) {
Log.e("IOException : "+e, e.getMessage());
}
Perhaps you can do following step to import library into your Android.
requirement library
- apache-mime4j-0.6.jar
- httpmime-4.0.1.jar
Right click your project and click properties
select java build path
select tab called "Order and Export"
Apply it
Fully uninstall you apk file with the adb uninstall due to existing apk not cater for new library
install again your apk
run it
Thanks,
Jenz
I'm having the same problem. I'm trying to upload an image through MultiPart Entity and it seens that the several updates on HttpClient/MIME are cracking everything. I'm trying the following code, falling with an Error "NoClassDefFoundError":
public static void executeMultipartPost(File image, ArrayList<Cookie> cookies, String myUrlToPost) {
try {
// my post instance
HttpPost httppost = new HttpPost(myUrlToPost);
// setting cookies for the connection session
if (cookies != null && cookies.size() > 0) {
String cookieString = "";
for (int i=0; i<cookies.size(); ++i) {
cookieString += cookies.get(i).getName()+"="+cookies.get(i).getValue()+";";
}
cookieString += "domain=" + BaseUrl + "; " + "path=/";
httppost.addHeader("Cookie", cookieString);
}
// creating the http client
HttpClient httpclient = new DefaultHttpClient();
// creating the multientity part [ERROR OCCURS IN THIS BELLOW LINE]
MultipartEntity multipartEntity = new MultipartEntity();
multipartEntity.addPart("photoupload", new FileBody(image));
httppost.setEntity(multipartEntity);
HttpResponse response = httpclient.execute(httppost);
HttpEntity resEntity = response.getEntity();
} catch (Exception e) {}
}
This method is fully compilable and uses the httpclient-4.0.1.jar and httpmime-4.2.jar libs, but again, I remember that it crashs in the commented line for me.
Related
I am trying to send a file from an android phone to a distant server. This is the code I used:
public void sendFile() {
try {
// HttpClient
HttpClient client = new DefaultHttpClient();
// post header
HttpPost post = new HttpPost("http://example.com/get_data.php");
// add your data
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
File folder = this.mContext.getFilesDir();
File file = new File(folder, "test.txt");
if (file.exists()) {
Log.d(TAG, "File exists : " + folder.listFiles()[0].toString());
}
builder.addPart("file", new FileBody(file));
builder.addBinaryBody("file", file);
HttpEntity entity = builder.build();
post.setEntity(entity);
HttpResponse response = client.execute(post);
HttpEntity Httpentity = response.getEntity();
Log.v("result", EntityUtils.toString(Httpentity));
} catch (Exception e) {
e.printStackTrace();
}
}
This code should be correct since I found similar examples here and there. The problem occurs when I build the MultipartEntityBuilder:
HttpEntity entity = builder.build();
I get this error:
Caused by: java.lang.NoClassDefFoundError: Failed resolution of: Lorg/apache/http/util/Args;
at org.apache.http.entity.mime.content.AbstractContentBody.<init>(AbstractContentBody.java:48)
at org.apache.http.entity.mime.content.FileBody.<init>(FileBody.java:96)
at org.apache.http.entity.mime.MultipartEntityBuilder.addBinaryBody(MultipartEntityBuilder.java:141)
at org.apache.http.entity.mime.MultipartEntityBuilder.addBinaryBody(MultipartEntityBuilder.java:146)
at com.example.kevin.recordacceleration.Accelerometer.sendFile(Accelerometer.java:149)
The file I'm trying to send is in the internal memory, and I check its existence: it exists.
Here are the libraries that I added:
It is not the latest version because I read on an other topic that this version of httpmime and httpclient should work
Your app is missing commons-codec and commons-logging on which HttpCore and HttpClient depends. Httpmime depends on HttpClient.
I would like to send a file to a server. Currently the code I use includes deprecated classes. How can I update the code to be uptodate?
protected String doInBackground(String... params) {
File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath(), params[0]);
try {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(server);
InputStreamEntity reqEntity = new InputStreamEntity(new FileInputStream(file), -1);
reqEntity.setContentType("binary/octet-stream");
reqEntity.setChunked(true); // Send in multiple parts if needed
httppost.setEntity(reqEntity);
HttpResponse response = httpclient.execute(httppost);
//Do something with response...
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
I suggest you to use this library : retrofit
http://square.github.io/retrofit/
I use it on my project right now and it helps me a lot with my http requests.
Moreover the documentation is really good.
I have been trying to upload an image and data to Django server. I have included apache-mime4j.0.6.jar and httpmime4.0.1.jar libraries ( Project->build path->Add external jar files)
And here's the code to upload an image.
HttpResponse response = null;
try {
HttpPost httppost = new HttpPost("http://10.0.2.2:8000/mobile");
// HttpPost httppost = new HttpPost("some url");
MultipartEntity multipartEntity = new MultipartEntity(); //MultipartEntity multipartEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
multipartEntity.addPart("name", new StringBody("nameText"));
multipartEntity.addPart("place", new StringBody("placeText"));
multipartEntity.addPart("tag", new StringBody("tagText"));
//multipartEntity.addPart("Description", new StringBody(Settings.SHARE.TEXT));
multipartEntity.addPart("Image", new FileBody(destination));
httppost.setEntity(multipartEntity);
httpclient.execute(httppost, new PhotoUploadResponseHandler());
} catch (Exception e) {
Log.e( "Error","error");
}
Error message:
Could not find class 'org.apache.http.entity.mime.MultipartEntity'
And I have tried manually creating libs folder and manually including jar files into /libs folder.
When I do that It fails to compile.
Error:
Conversion to Dalvik format failed with error 1 Unknown Android Packaging Problem
Tried creating fresh application including libraries. And I encountered the same error. I've tried everything possible. Can anyone tell me why this happens and how to fix it. Any help would be greatly appreciated!!
If you are using new android-sdk Try this.
Create folder named as libs
Paste your jar file in that folder.
And finally right click on your project > Build Path > Add External Archive.
That's it.This might help.Good Luck.
I upload an image from Android to a Django server using httpmime-4.2.1.jar. That is the only library that i have included and it works fine. Btw: libraries are supposed to be in the libs folder in Android projects.
this is the code that i am using for the upload.
private JSONObject uploadImage(String url, File img) throws Exception{
url = addAuthToken(url);
HttpPost post = new HttpPost(url);
MultipartEntity reqEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
FileBody fileBody = new FileBody(img, "images/jpeg");
reqEntity.addPart("image", fileBody);
post.setEntity(reqEntity);
JSONObject ret = baseRequest(post);
checkReturnStatus(ret, 201);
return ret;
}
private JSONObject baseRequest(HttpUriRequest request) throws Exception{
HttpClient client = new DefaultHttpClient();
HttpResponse response = client.execute(request);
BufferedReader in = null;
try{
in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
StringBuffer sb = new StringBuffer();
String line = null;
String NL = System.getProperty("line.separator");
while ((line = in.readLine()) != null) {
sb.append(line + NL);
}
return new JSONObject(sb.toString());
}finally {
if(in != null) in.close();
}
}
I suggest you to use spring-android
It is a good rest api library for android and with spring-android, you can upload file easily like this.
HttpHeaders requestHeaders = ....
MultiValueMap<String, Object> message = new LinkedMultiValueMap<String, Object>();
message.add("qqfile", new FileSystemResource(filePath)); //attach file
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<MultiValueMap<String, Object>>(
message, requestHeaders);
RestTemplate restTemplate = RestUtil.getRestTemplate( context);
ResponseEntity<YourResultDTO> response = restTemplate.exchange(url, HttpMethod.POST, requestEntity,YourResultDTO.class);
It is very easy to use and use Apache http client on pre gingerbread and java.net.urlconnection on gingerbread and higher api level as google suggests.
I had the same problem and I solved it this way: in the java build path window, click the Order and Export tab Highlight the library you want to add then click the up (upload lib to be first)
Click ok and everything is fine.
Here is a link with photos (Android Eclipse NoClassDefFoundError for external .jar files)
I'm dealing with the following problem: when trying to upload an image through MultiPart Entity and it seems that the several updates on HttpClient/MIME are cracking everything. I'm trying the following code, but it fails with a NoClassDefFoundError:
public static void executeMultipartPost(File image, ArrayList<Cookie> cookies, String myUrlToPost) {
try {
// my post instance
HttpPost httppost = new HttpPost(myUrlToPost);
// setting cookies for the connection session
if (cookies != null && cookies.size() > 0) {
String cookieString = "";
for (int i=0; i<cookies.size(); ++i) {
cookieString += cookies.get(i).getName()+"="+cookies.get(i).getValue()+";";
}
cookieString += "domain=" + BaseUrl + "; " + "path=/";
httppost.addHeader("Cookie", cookieString);
}
// creating the http client
HttpClient httpclient = new DefaultHttpClient();
// creating the multientity part [ERROR OCCURS IN THIS BELLOW LINE]
MultipartEntity multipartEntity = new MultipartEntity();
multipartEntity.addPart("photoupload", new FileBody(image));
httppost.setEntity(multipartEntity);
HttpResponse response = httpclient.execute(httppost);
HttpEntity resEntity = response.getEntity();
} catch (Exception e) {}
}
This method is fully compilable and uses the httpclient-4.0.1.jar and httpmime-4.2.jar libs, but again, it crashes on the commented line for me.
Am I missing something?
Ok, here you have libraries needed for Multipart post, all credits to Satya Komatineni and David Maclean, writers of Pro Android 3 and now 4 and I quote from their book
To do multipart POST calls, you need to get three additional Apache
open source projects: Apache Commons IO, Mime4j, and HttpMime. You
can download these projects from the following web sites: Commons
IO: http://commons.apache.org/io/ Mime4j:
http://james.apache.org/mime4j/ HttpMime:
http://hc.apache.org/downloads.cgi (inside of HttpClient)
I have the same problem and it was fixed by moving jars files into 'libs' directory in your android project.
Make sure the jar is checked in the projects build path. (Project -> Properties)
I need to upload an image to my server under a specific name, but ideally, I would like to still keep image stored on the device under the original file name. This is what I tried:
myImageFile.renameTo(new File("mobileimage.jpg"));
but when the file was uploaded to the server, it did not appear to have my new name. Here is the full code that uploads the image to the server:
DefaultHttpClient mHttpClient;
HttpParams params = new BasicHttpParams();
params.setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
mHttpClient = new DefaultHttpClient(params);
try {
myImageFile.renameTo(new File("mobileimage.jpg"));
HttpPost httppost = new HttpPost("http://mywebsite/mobile/image");
MultipartEntity multipartEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
multipartEntity.addPart("userID", new StringBody(Constants.userID));
multipartEntity.addPart("uniqueMobileID", new StringBody(Constants.uniqueMobileID));
multipartEntity.addPart("userfile", new FileBody(myImageFile));
httppost.setEntity(multipartEntity);
HttpResponse response = mHttpClient.execute(httppost);
String responseBody = EntityUtils.toString(response.getEntity());
Log.d(TAG, "response: " + responseBody);
return responseBody;
} catch (Exception e) {
Log.d(TAG, e.getMessage());
}
How can I change the file name?
Use the constructor of FileBody that takes the fileName as an argument
Try using the other implementation of addPart when attaching the file, so that you may add the filename field to the HTTP request. Something like this:
FormBodyPart userFile = new FormBodyPart("userfile", new FileBody(myImageFile));
userFile.addField("filename","NEWNAMEOFILE.jpg");
multipartEntity.addPart(userFile);
Is it possible renameTo() is returning false? You should check your return values, especially with renameTo().