Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

File Upload with Java (with progress bar)

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.

like image 255
soapergem Avatar asked Oct 31 '08 19:10

soapergem


People also ask

What is multipart file upload in Java?

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 ).


2 Answers

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.

like image 159
tuler Avatar answered Sep 23 '22 16:09

tuler


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));     } } 
like image 30
ankostis Avatar answered Sep 21 '22 16:09

ankostis