无法抓取http POST文件上传进度(Android)

Man*_*uel 17 upload post android http progress

我正在开发一个Android应用程序,使用户能够将文件上传到Twitpic等服务.POST上传完成后没有任何外部库,工作正常.我唯一的问题是,我不能抓住任何进展,因为所有的上传是,当我完成接收不同时响应,字节到输出流.这是我做的:

URL url = new URL(urlString); 
HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 
conn.setDoInput(true); 
conn.setDoOutput(true); 
conn.setUseCaches(false); 
conn.setRequestMethod("POST"); 
conn.setRequestProperty("Connection", "Keep-Alive"); 
conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary); 
DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
Run Code Online (Sandbox Code Playgroud)

然后我将表单数据写入dos,现在这里并不重要.之后我自己编写文件数据(从"in"读取,这是我要发送的数据的InputStream):

while ((bytesAvailable = in.available()) > 0)
{ 
 bufferSize = Math.min(bytesAvailable, maxBufferSize);
 byte[] buffer = new byte[bufferSize];
 bytesRead = in.read(buffer, 0, bufferSize);
 dos.write(buffer, 0, bytesRead);
} 
Run Code Online (Sandbox Code Playgroud)

之后,我发送多部分表单数据以指示文件的结尾.然后,我关闭流:

in.close(); 
dos.flush(); 
dos.close(); 
Run Code Online (Sandbox Code Playgroud)

这一切都很好,到目前为止没问题.然而,我的问题是,无论文件有多大,到目前为止的整个过程大约需要一到两秒钟.当我阅读回复时,上传本身似乎发生了:

DataInputStream inStream = new DataInputStream(conn.getInputStream());
Run Code Online (Sandbox Code Playgroud)

这需要几秒钟或几分钟,具体取决于文件的大小和Internet连接的速度.我现在的问题是:1)当我将字节写入"dos"时,为什么不发生uplaod?2)如果一次发生所有事情,我怎样才能获取进度以便在上传过程中显示进度对话框?

/编辑:1)我在标题中设置了Content-Length,它稍微改变了问题,但没有以任何方式解决它:现在整个内容在最后一个字节写入流后上传.因此,这不会改变您无法获取进度的情况,因为同样,数据会立即写入.2)我在Apache HttpClient v4中尝试了MultipartEntity.在那里你根本没有OutputStream,因为在执行请求时会写入所有数据.再说一次,没有办法抓住进步.

有没有人有任何其他想法如何在多部分/表单上传中获取进程?

Man*_*uel 20

我在最后几天尝试了很多,我想我对最初的问题有了答案:

使用HttpURLConnection获取进度是不可能的,因为Android中存在错误/异常行为:http://code.google.com/p/android/issues/detail? id = 3164#c6

它将在Froyo后固定,这不是人们可以等待的东西......

因此,我发现的唯一其他选项是使用Apache HttpClient.在通过papleu链接的答案是正确的,但它指的是一般的Java.在那里使用的类不再在Android中可用(HttpClient 3.1是SDK的一部分,一次).所以,你可以做的是添加来自HttpClient 4的库(特别是apache-mime4j-0.6.jar和httpmime-4.0.1.jar)并使用第一个答案(Tuler)和最后一个答案(由Hamy组合) ):

import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntity;

public class CountingMultipartEntity extends MultipartEntity {

    private final ProgressListener listener;

    public CountingMultipartEntity(final ProgressListener listener) {
        super();
        this.listener = listener;
    }

    public CountingMultipartEntity(final HttpMultipartMode mode, final ProgressListener listener) {
        super(mode);
        this.listener = listener;
    }

    public CountingMultipartEntity(HttpMultipartMode mode, final String boundary,
            final Charset charset, final ProgressListener listener) {
        super(mode, boundary, charset);
        this.listener = listener;
    }

    @Override
    public void writeTo(final OutputStream outstream) throws IOException {
        super.writeTo(new CountingOutputStream(outstream, 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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这适用于HttpClient 4,但缺点是我的apk现在的大小为235 kb(当我使用我的问题中描述的分段上传时它是90 kb),更糟糕的是,安装的应用程序大小为735 kb(约之前170 kb).那太可怕了.只是为了在上传过程中取得进步,应用程序大小现在是以前的4倍.