The short version - org.apache...MultipartEntity
is deprecated, and its upgrade, MultipartEntityBuilder
, appears under-represented in our online forums. Let's fix that. How does one register a callback, so my (Android) app can display a progress bar as it uploads a file?
The long version - Here's the "missing dirt-simple example" of MultipartEntityBuilder
:
public static void postFile(String fileName) throws Exception {
// Based on: https://stackoverflow.com/questions/2017414/post-multipart-request-with-android-sdk
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(SERVER + "uploadFile");
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
builder.addPart("file", new FileBody(new File(fileName)));
builder.addTextBody("userName", userName);
builder.addTextBody("password", password);
builder.addTextBody("macAddress", macAddress);
post.setEntity(builder.build());
HttpResponse response = client.execute(post);
HttpEntity entity = response.getEntity();
// response.getStatusLine(); // CONSIDER Detect server complaints
entity.consumeContent();
client.getConnectionManager().shutdown();
} // FIXME Hook up a progress bar!
We need to fix that FIXME
. (An added benefit would be interruptible uploads.) But (please correct me whether or not I'm wrong), all the online examples seem to fall short.
This one, http://pastebin.com/M0uNZ6SB, for example, uploads a file as a "binary/octet-stream"; not a "multipart/form-data". I require real fields.
This example, File Upload with Java (with progress bar), shows how to override the *Entity
or the *Stream
. So maybe I can tell the MultipartEntityBuilder
to .create()
an overridden entity that meters its upload progress?
So if I want to override something, and replace the built-in stream with a counting stream that sends a signal for every 1000 bytes, maybe I can extend the FileBody
part, and override its getInputStream
and/or writeTo
.
But when I try class ProgressiveFileBody extends FileBody {...}
, I get the infamous java.lang.NoClassDefFoundError
.
So while I go spelunking around my .jar
files, looking for the missing Def, can someone check my math, and maybe point out a simpler fix I have overlooked?
first of all: huge thanks for the original question/answer. Since HttpPost is now deprecated, I reworked it a bit though, using additional input from this article and made a micro library of it: https://github.com/licryle/HTTPPoster
It wraps the whole in an ASync task; uses the MultipartEntityBuilder & HttpURLConnection and let's you listen for callbacks.
To use:
You need a class to implement the
HttpListener
interface so you can listen to the callbacks. It has four callbacks inHTTPListener
:Configure the ASyncTask & start it. Here's a quick usage:
hope that can help :) Feel also free to suggest improvements! It's very recent, and I extend it as I need it.
Cheers
The winning code (in spectacular Java-Heresy(tm) style) is:
Cant thank Phlip enough for that solution. Here are the final touches for adding your progressbar support. I ran it inside an AsyncTask - progress below enables you to post the progress back to a method in the AsyncTask that invokes AsyncTask.publishProgress() for your class running in the AsyncTask. The progress bar isn't exactly smooth but at least it moves. On a Samsung S4 uploading a 4MB imagefile after the preamble it was moving 4K chunks.