I'm extremely new to Java, and have mostly just been teaching myself as I go, so I've started building an applet. I'd like to make one that can select a file from the local disk and upload it as a multipart/form-data POST request but with a progress bar. Obviously the user has to grant permission to the Java applet to access the hard drive. Now I've already got the first part working: the user can select a file using a JFileChooser
object, which conveniently returns a File
object. But I'm wondering what comes next. I know that File.length()
will give me the total size in bytes of the file, but how do I send the selected File
to the web, and how do I monitor how many bytes have been sent? Thanks in advance.
The standard way to upload files in a web application is to use a form with a special multipart/form-data encoding, which lets you mix standard form data with file attachment data. Note: The HTTP method used to submit the form must be POST (not GET ).
To check progress using HttpClient, wrap the MultipartRequestEntity around one that counts the bytes being sent. Wrapper is below:
import java.io.FilterOutputStream; import java.io.IOException; import java.io.OutputStream; import org.apache.commons.httpclient.methods.RequestEntity; public class CountingMultipartRequestEntity implements RequestEntity { private final RequestEntity delegate; private final ProgressListener listener; public CountingMultipartRequestEntity(final RequestEntity entity, final ProgressListener listener) { super(); this.delegate = entity; this.listener = listener; } public long getContentLength() { return this.delegate.getContentLength(); } public String getContentType() { return this.delegate.getContentType(); } public boolean isRepeatable() { return this.delegate.isRepeatable(); } public void writeRequest(final OutputStream out) throws IOException { this.delegate.writeRequest(new CountingOutputStream(out, this.listener)); } public static interface ProgressListener { void transferred(long num); } public static class CountingOutputStream extends FilterOutputStream { private final ProgressListener listener; private long transferred; public CountingOutputStream(final OutputStream out, final ProgressListener listener) { super(out); this.listener = listener; this.transferred = 0; } public void write(byte[] b, int off, int len) throws IOException { out.write(b, off, len); this.transferred += len; this.listener.transferred(this.transferred); } public void write(int b) throws IOException { out.write(b); this.transferred++; this.listener.transferred(this.transferred); } } }
Then implements a ProgressListener which updates a progress bar.
Remember that the progress bar update must not run on the Event Dispatch Thread.
A simpler countingEntity would not depend on a specific entity type but rather extend HttpEntityWrapped
:
package gr.phaistos.android.util; import java.io.FilterOutputStream; import java.io.IOException; import java.io.OutputStream; import org.apache.http.HttpEntity; import org.apache.http.entity.HttpEntityWrapper; public class CountingHttpEntity extends HttpEntityWrapper { public static interface ProgressListener { void transferred(long transferedBytes); } static class CountingOutputStream extends FilterOutputStream { private final ProgressListener listener; private long transferred; CountingOutputStream(final OutputStream out, final ProgressListener listener) { super(out); this.listener = listener; this.transferred = 0; } @Override public void write(final byte[] b, final int off, final int len) throws IOException { //// NO, double-counting, as super.write(byte[], int, int) delegates to write(int). //super.write(b, off, len); out.write(b, off, len); this.transferred += len; this.listener.transferred(this.transferred); } @Override public void write(final int b) throws IOException { out.write(b); this.transferred++; this.listener.transferred(this.transferred); } } private final ProgressListener listener; public CountingHttpEntity(final HttpEntity entity, final ProgressListener listener) { super(entity); this.listener = listener; } @Override public void writeTo(final OutputStream out) throws IOException { this.wrappedEntity.writeTo(out instanceof CountingOutputStream? out: new CountingOutputStream(out, this.listener)); } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With