通过带有进度条的 MultipartEntityBuilder 通过 HTTP 表单上传文件 [英] Upload a file through an HTTP form, via MultipartEntityBuilder, with a progress bar

查看:29
本文介绍了通过带有进度条的 MultipartEntityBuilder 通过 HTTP 表单上传文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

简短版本 - org.apache...MultipartEntity 已弃用,其升级版 MultipartEntityBuilder 在我们的在线论坛.让我们解决这个问题.如何注册回调,以便我的(Android)应用在上传文件时显示进度条?

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?

长版本 - 这是 MultipartEntityBuilder 的缺​​失的简单示例":

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!

我们需要修复那个FIXME.(一个额外的好处是可以中断上传.)但是(请纠正我,无论我错了),所有在线示例似乎都不足.

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.

这个以http://pastebin.com/M0uNZ6SB为例,上传一个文件作为二进制/八位字节流";不是多部分/表单数据".我需要真实的字段.

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.

此示例,使用 Java 上传文件(带进度条),显示如何覆盖 *Entity*Stream.所以也许我可以告诉 MultipartEntityBuilder.create() 一个覆盖其上传进度的实体?

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?

因此,如果我想覆盖某些内容,并将内置流替换为每 1000 个字节发送一个信号的计数流,也许我可以扩展 FileBody 部分,并覆盖其 getInputStream 和/或 writeTo.

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.

但是当我尝试 class ProgressiveFileBody extends FileBody {...} 时,我得到了臭名昭著的 java.lang.NoClassDefFoundError.

But when I try class ProgressiveFileBody extends FileBody {...}, I get the infamous java.lang.NoClassDefFoundError.

所以当我在我的 .jar 文件周围进行探索时,寻找丢失的 Def,有人可以检查我的数学,也许可以指出我忽略的更简单的修复吗?

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?

推荐答案

获奖代码(采用壮观的 Java-Heresy(tm) 风格)是:

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 {
                    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);
                }
                public void write(byte[] bts, int st, int end) throws IOException {

                    // FIXME  Put your progress bar stuff here!

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

            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 + "
";
    }
    return content.trim();
}

#  NOTE ADDED LATER: as this blasterpiece gets copied into various code lineages, 
#  The management reminds the peanut gallery that "Java-Heresy" crack was there
#  for a reason, and (as commented) most of that stuff can be farmed out to off-
#  the-shelf jar files and what-not. That's for the java lifers to tool up. This
#  pristine hack shall remain obviousized for education, and for use in a pinch.

#  What are the odds??

这篇关于通过带有进度条的 MultipartEntityBuilder 通过 HTTP 表单上传文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆