有啥方法可以使用 HttpUrlConnection 正确获取上传进度

Posted

技术标签:

【中文标题】有啥方法可以使用 HttpUrlConnection 正确获取上传进度【英文标题】:Is there any way to get upload progress correctly with HttpUrlConncetion有什么方法可以使用 HttpUrlConnection 正确获取上传进度 【发布时间】:2013-08-08 15:14:57 【问题描述】:

android 开发者博客推荐使用HttpURLConnection 而不是apache 的HttpClient (http://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);

无论文件大小如何,此代码的执行速度都非常快,但文件实际上仍在上传到服务器 util 我从服务器获得响应。当我调用out.write() 时,HttpURLConnection 似乎将所有数据缓存在内部缓冲区中。

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

【问题讨论】:

作为不使用 apache 客户端的明智开发人员之一,您获得了惊人的 +1。在这个网站上以 apache 客户端的名义看到了一些 Android 中最糟糕的网络决策。其次,通常进度与上传大文件有关。你的文件有多大?如果是这样,分块传输编码是否适合您的文件? @Tom 我的应用需要支持上传不大于30m的文件,而服务器端现在不支持分块传输编码... @Toki 这是旧的,但如果你想知道你在第 2 行拼错了连接。 【参考方案1】:

我在开发者文档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() 解决我的问题。 但是正如this post 所提到的,android 中有一个错误使得HttpURLConnection 缓存所有内容,即使setFixedLengthStreamingMode() 已被调用,直到后froyo 才修复。所以我使用 HttpClient 代替 pre-gingerbread。

【讨论】:

这是我在 *** 上读到的关于这个问题的最有帮助的内容。很多人只是跟踪写入缓冲区并认为他们解决了问题。 @toki,这个 bug 现在的状态如何?【参考方案2】:

使用 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);

【讨论】:

我不认为 OP 在为此制作 UI 时遇到问题。 OP 希望可靠地解释有多少流已被读取到套接字上。 “总数”从何而来? Tom 是对的,我想要一种方法来获取上传文件时的网络传输进度,这正是在套接字层向服务器发送了多少字节。

以上是关于有啥方法可以使用 HttpUrlConnection 正确获取上传进度的主要内容,如果未能解决你的问题,请参考以下文章

有啥方法可以创建一个使用 WrappedComponent 中的方法的 HOC?

有啥方法可以使用 SwiftUI 创建 BottomBar

GeotriggerHandlerReceiver 在 PlotProjects 中已弃用。有啥替代方法可以使用?

有啥方法可以使用 H.S.V 选择表面颜色吗?

CLLocationManager:有啥方法可以使用 requestAlwaysAuthorization 并且仍然有蓝条?

有啥方法可以使用角度组件中的 onCall Firebase 函数?