You are viewing a plain text version of this content. The canonical link for it is here.
Posted to httpclient-users@hc.apache.org by Phlip <ph...@gmail.com> on 2013/10/03 23:50:36 UTC

Upload a file through an HTTP form, via MultipartEntityBuilder, with a progress bar

Here's an example of MultipartEntityBuilder in action:

public static void postFile(String fileName) throws Exception {
    // Based on:
http://stackoverflow.com/questions/2017414/post-multipart-request-with-android-sdk

    HttpClient client = new DefaultHttpClient();
    HttpPost post = new HttpPost(SERVER + "uploadFile");
    MultipartEntityBuilder multipartEntity =
MultipartEntityBuilder.create();
    multipartEntity.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
    multipartEntity.addPart("file", new FileBody(new File(fileName)));
    post.setEntity(multipartEntity.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!

How do I add a progress bar? Should I extend the FileBody class,
override its getInputStream(), and return an input stream with an
overridden .write that counts the bytes & sends View commands. (I'm
inside Android, if that helps...)

-- 
  Phlip
  http://c2.com/cgi/wiki?ZeekLand

---------------------------------------------------------------------
To unsubscribe, e-mail: httpclient-users-unsubscribe@hc.apache.org
For additional commands, e-mail: httpclient-users-help@hc.apache.org


Re: Upload a file through an HTTP form, via MultipartEntityBuilder, with a progress bar

Posted by Phlip <ph...@gmail.com>.
> You do not need to get inside of #create. Just decorate the instance you get
> from #build. HttpEntity is an interface and lends itself well to the proxy or
> decorator pattern.

Thanks, got it.

Anecdotally, I had first tried to extend FileBody. The extended class
worked in production, but not in Junit test, which caught the infamous
NoClassDefFoundError error.

The winning code (in spectacular Java-Heresy(tm) style), is:

    public static String postFile(String fileName, String userName,
String password, String macAddress) throws Exception {

        HttpClient client = new DefaultHttpClient();
        HttpPost post = new HttpPost(SERVER + "uploadFile");
        MultipartEntityBuilder builder =
MultipartEntityBuilder.create();
        builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);

        final File file = new File(fileName);
        FileBody fb = new FileBody(file);

        builder.addPart("file", fb);
        builder.addTextBody("userName", userName);
        builder.addTextBody("password", password);
        builder.addTextBody("macAddress",  macAddress);
        final HttpEntity yourEntity = builder.build();

        class ProgressiveEntity implements HttpEntity {
            @Override
            public void consumeContent() throws IOException {
                yourEntity.consumeContent();
            }
            @Override
            public InputStream getContent() throws IOException,
                    IllegalStateException {
                return yourEntity.getContent();
            }
            @Override
            public Header getContentEncoding() {
                return yourEntity.getContentEncoding();
            }
            @Override
            public long getContentLength() {
                return yourEntity.getContentLength();
            }
            @Override
            public Header getContentType() {
                return yourEntity.getContentType();
            }
            @Override
            public boolean isChunked() {
                return yourEntity.isChunked();
            }
            @Override
            public boolean isRepeatable() {
                return yourEntity.isRepeatable();
            }
            @Override
            public boolean isStreaming() {
                return yourEntity.isStreaming();
            } // CONSIDER put a _real_ delegator into here!

            @Override
            public void writeTo(OutputStream outstream) throws IOException {

                class ProxyOutputStream extends FilterOutputStream {
                    /**
                     * @author Stephen Colebourne
                     */

                    public ProxyOutputStream(OutputStream proxy) {
                        super(proxy);
                    }
                    public void write(int idx) throws IOException {
                        out.write(idx);
                    }
                    public void write(byte[] bts) throws IOException {
                        out.write(bts);
                    }

                    public void write(byte[] bts, int st, int end)
throws IOException {

                        // FIXME  Put your progress bar stuff here!

                        out.write(bts, st, end);
                    }

                    public void flush() throws IOException {
                        out.flush();
                    }
                    public void close() throws IOException {
                        out.close();
                    }
                } // CONSIDER import this class (and risk more Jar File Hell)

                class ProgressiveOutputStream extends ProxyOutputStream {
                    public ProgressiveOutputStream(OutputStream proxy) {
                        super(proxy);
                    }
                }

                yourEntity.writeTo(new ProgressiveOutputStream(outstream));
            }

        };
        ProgressiveEntity myEntity = new ProgressiveEntity();

        post.setEntity(myEntity);
        HttpResponse response = client.execute(post);

        return getContent(response);

    }

    public static String getContent(HttpResponse response) throws IOException {
        BufferedReader rd = new BufferedReader(new
InputStreamReader(response.getEntity().getContent()));
        String body = "";
        String content = "";

        while ((body = rd.readLine()) != null)
        {
            content += body + "\n";
        }
        return content.trim();
    }

---------------------------------------------------------------------
To unsubscribe, e-mail: httpclient-users-unsubscribe@hc.apache.org
For additional commands, e-mail: httpclient-users-help@hc.apache.org


Re: Upload a file through an HTTP form, via MultipartEntityBuilder, with a progress bar

Posted by Oleg Kalnichevski <ol...@apache.org>.
You do not need to get inside of #create. Just decorate the instance you get from #build. HttpEntity is an interface and lends itself well to the proxy or decorator pattern.

Oleg


Phlip <ph...@gmail.com> wrote:
>> You need to decorate the resultant HttpEntity
>
>If we're using MultipartEntityBuilder, how do I get inside .create()
>to change the builder to a derived type?
>
>---------------------------------------------------------------------
>To unsubscribe, e-mail: httpclient-users-unsubscribe@hc.apache.org
>For additional commands, e-mail: httpclient-users-help@hc.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: httpclient-users-unsubscribe@hc.apache.org
For additional commands, e-mail: httpclient-users-help@hc.apache.org


Re: Upload a file through an HTTP form, via MultipartEntityBuilder, with a progress bar

Posted by Phlip <ph...@gmail.com>.
> You need to decorate the resultant HttpEntity

If we're using MultipartEntityBuilder, how do I get inside .create()
to change the builder to a derived type?

---------------------------------------------------------------------
To unsubscribe, e-mail: httpclient-users-unsubscribe@hc.apache.org
For additional commands, e-mail: httpclient-users-help@hc.apache.org


Re: Upload a file through an HTTP form, via MultipartEntityBuilder, with a progress bar

Posted by Oleg Kalnichevski <ol...@apache.org>.
On Thu, 2013-10-03 at 14:50 -0700, Phlip wrote:
> Here's an example of MultipartEntityBuilder in action:
> 
> public static void postFile(String fileName) throws Exception {
>     // Based on:
> http://stackoverflow.com/questions/2017414/post-multipart-request-with-android-sdk
> 
>     HttpClient client = new DefaultHttpClient();
>     HttpPost post = new HttpPost(SERVER + "uploadFile");
>     MultipartEntityBuilder multipartEntity =
> MultipartEntityBuilder.create();
>     multipartEntity.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
>     multipartEntity.addPart("file", new FileBody(new File(fileName)));
>     post.setEntity(multipartEntity.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!
> 
> How do I add a progress bar? Should I extend the FileBody class,
> override its getInputStream(), and return an input stream with an
> overridden .write that counts the bytes & sends View commands. (I'm
> inside Android, if that helps...)
> 

You need to decorate the resultant HttpEntity and inside #writeTo method
wrap the original OutputStream with a ProxyOutputStream [1] subclass or
a similar implementation and have it update the UI.

Oleg

[1]
http://commons.apache.org/proper/commons-io/javadocs/api-release/org/apache/commons/io/output/ProxyOutputStream.html



---------------------------------------------------------------------
To unsubscribe, e-mail: httpclient-users-unsubscribe@hc.apache.org
For additional commands, e-mail: httpclient-users-help@hc.apache.org