如何在下载文件之前知道文件的大小?

37

我需要下载一个文件,使用的是这段代码,它基本上是一个AsyncTask,用于更新进度条。但是,由于我不知道文件大小,因此一直在使用旋转进度条。那么,我该如何在开始下载文件之前获取文件大小,以便使用普通进度条呢?


请注意,在尝试访问“Content-Length”标头之前,您应该调用urlConnection.connect()。不这样做可能会起作用,但并非在所有可能的情况下都是如此。 - Felix
不知道...对我来说是这样工作的,但感谢你的建议。我要编辑答案。 - Cristian
2个回答

76

您可以从获得的HTTP响应对象中获取名为Content-Length的标头,这将告诉您文件的长度。

需要注意的是,有些服务器不返回该信息,唯一知道实际大小的方法是从响应中读取所有内容。

示例:

URL url = new URL("http://server.com/file.mp3");
URLConnection urlConnection = url.openConnection();
urlConnection.connect();
int file_size = urlConnection.getContentLength();

这将适用于大多数情况,但如果文件太大,则无法正常工作。请参阅我在下面发布的解决方案:https://dev59.com/qXA85IYBdhLWcg3wBOtO#12271781 - android developer
1
对于 Android 7 及以上版本,应使用 getContentLengthLong() 而不是 getContentLength()。在此之下,建议使用 Long.parseLong(urlConnection.getHeaderField("content-length"))。 - Sandeep

19

你通常可以使用getContentLength,但最好自己获取长度(因为它可以绕过整数的最大值)。

自己解析content-length头部的值。最好将其解析成长整型。

示例:

final URL uri=new URL(...);
URLConnection ucon;
try
  {
  ucon=uri.openConnection();
  ucon.connect();
  final String contentLengthStr=ucon.getHeaderField("content-length");
  //...
  }
catch(final IOException e1)
  {
  }

请注意,变量i可以是任何字符串,因此请使用try-catch语句。如果i的值为-1、空或null,则意味着您无法知道文件的大小,因为服务器不允许。

编辑:以下是使用Kotlin更新后的代码:

@JvmStatic
@WorkerThread
fun getFileSizeOfUrl(url: String): Long {
    var urlConnection: URLConnection? = null
    try {
        val uri = URL(url)
        urlConnection = uri.openConnection()
        urlConnection!!.connect()
        if (VERSION.SDK_INT >= Build.VERSION_CODES.N)
            return urlConnection.contentLengthLong
        val contentLengthStr = urlConnection.getHeaderField("content-length")
        return if (contentLengthStr.isNullOrEmpty()) -1L else contentLengthStr.toLong()
    } catch (ignored: Exception) {
    } finally {
        if (urlConnection is HttpURLConnection)
            urlConnection.disconnect()
    }
    return -1L
}

1
Java的int原始类型是32位有符号整数;您可能不会通过Content-Type头超过最大值。 - mjama
5
实际上你可以,它大约有2GB。 - android developer
@KalpeshLakhani 我不了解服务器端,只知道客户端。这里的问题是关于Android的,它在这种情况下作为客户端。抱歉。也许这些链接可以帮助:http://stackoverflow.com/questions/6918016/how-to-configure-httpserver-to-use-content-length-and-not-transfer-encoding-chu https://dev59.com/mG7Xa4cB1Zd3GeqPq4cw - android developer
@KalpeshLakhani,我不确定你在问什么。如果你是在询问应用程序已经下载了文件URL的数据量,那么这就是下载文件的“算法”之一——你的循环包括从inputStream中读取,并且你增加一个计数器以知道到目前为止读取了多少字节。InputStream的“read”方法返回读取的字节数:http://developer.android.com/reference/java/io/InputStream.html#read(byte[])。这里有一个示例用法:https://dev59.com/WXE95IYBdhLWcg3wCJRf#2509258。 - android developer
@KalpeshLakhani 好的,我写的是字节,所以你只需要将结果除以1024就可以得到千字节(kb=千位元,KB=千字节)。 - android developer
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接