问题 有没有办法通过HttpUrlConncetion正确上传进度


Android开发者博客建议使用 HttpURLConnection 除了阿帕奇之外 HttpClienthttp://android-developers.blogspot.com/2011/09/androids-http-clients.html)。我接受了建议 并在报告文件上传进度时遇到问题。

我抓住进度的代码是这样的:

try {
    out = conncetion.getOutputStream();
    in = new BufferedInputStream(fin);
    byte[] buffer = new byte[MAX_BUFFER_SIZE];
    int r;
    while ((r = in.read(buffer)) != -1) {
        out.write(buffer, 0, r);
        bytes += r;
        if (null != mListener) {
            long now = System.currentTimeMillis();
            if (now - lastTime >= mListener.getProgressInterval()) {
                lastTime = now;
                if (!mListener.onProgress(bytes, mSize)) {
                    break;
                }
            }
        }
    }
    out.flush();
} finally {
    closeSilently(in);
    closeSilently(out);
}

这个代码对于任何文件大小都非常快,但该文件实际上仍在上传到服务器,我从服务器获得响应。看起来 HttpURLConnection 我打电话时缓存内部缓冲区中的所有数据 out.write()

那么,我怎样才能获得实际的文件上传进度?似乎 httpclient 可以做到这一点,但是 httpclient 不是首选...任何想法?


2886
2017-08-07 09:46


起源

作为一个不使用apache客户端的合理开发人员之一,你获得了惊人的惊人+1。 Android中的一些最糟糕的网络决策已经在这个网站上以apache客户端的名义出现。其次,通常进度与上传大文件相关。你的档案有多大?如果是这样,是否适合您的文件的分块传输编码? - Tom
@Tom我的应用程序需要支持不超过30米的上传文件,服务器端现在不支持分块传输编码... - toki
@Toki这是旧的,但万一你想知道你在第2行拼错连接。 - charliebeckwith


答案:


我在开发者文档中找到了解释 http://developer.android.com/reference/java/net/HttpURLConnection.html

To upload data to a web server, configure the connection for output using setDoOutput(true).
For best performance, you should call either setFixedLengthStreamingMode(int) when the body length is known in advance, or setChunkedStreamingMode(int) when it is not. Otherwise HttpURLConnection will be forced to buffer the complete request body in memory before it is transmitted, wasting (and possibly exhausting) heap and increasing latency.

调用 setFixedLengthStreamingMode() 首先解决我的问题。 但正如提到的那样 这个帖子,android中有一个错误 HttpURLConnection 缓存所有内容即使 setFixedLengthStreamingMode() 被称为,直到后froyo,这是固定的。所以我用HttpClient代替预姜饼。


14
2017-08-13 08:49



这是我在StackOverflow上关于这个问题的最有用的东西。很多人只是跟踪写入缓冲区并认为他们解决了问题。 - Brian
@toki,现在这个bug的状态是什么? - avismara


使用Asynctask上传文件以将文件上传到服务器并创建Progressdialog

1)运行你的代码

 doinbackground(){
    your code here..
}

2)更新进度

publishProgress("" + (int) ((total * 100) / lenghtOfFile));
    //type this in the while loop before write..

3)和更新进度

protected void onProgressUpdate(String... progress) {
            Progress.setProgress(Integer.parseInt(progress[0]));
        }

4)驳回进度

protected void onPostExecute(String file_url) {
            dismissDialog(progress);

-2
2017-08-07 09:55



我不认为OP在为此制作UI时遇到问题。 OP想要获得有关已经读取了多少流到套接字的可靠解释。 “总”来自哪里? - Tom
Tom是对的,我希望在上传文件时能够获得网络传输进度,这正是在套接字层上向服务器发送了多少字节。 - toki