我正在为学校做一个项目,我正在实现一个可用于从网络下载文件的工具(带有节流选项)。问题是,我将有一个 GUI,我将使用一个JProgressBar
小部件,我想显示下载的当前进度。为此,我需要知道文件的大小。在下载文件之前如何获取文件的大小。
6 回答
任何 HTTP 响应都应该包含 Content-Length 标头,因此您可以在 URLConnection 对象中查询该值。
//once the connection has been opened
List values = urlConnection.getHeaderFields().get("content-Length")
if (values != null && !values.isEmpty()) {
// getHeaderFields() returns a Map with key=(String) header
// name, value = List of String values for that header field.
// just use the first value here.
String sLength = (String) values.get(0);
if (sLength != null) {
//parse the length into an integer...
...
}
服务器可能并不总是可以返回准确的 Content-Length,因此该值可能不准确,但至少在大多数情况下您会得到一些可用的值。
更新:或者,现在我更完整地查看了 URLConnection javadoc,您可以只使用getContentLength()方法。
如前所述,URLConnectiongetContentLengthLong()
是您最好的选择,但它并不总是给出明确的长度。那是因为 HTTP 协议(以及可以用 a 表示的其他协议URLConnection
)并不总是传达长度。
在 HTTP 的情况下,动态内容的长度通常是事先不知道的——content-length
通常何时发送标头。相反,另一个标头transfer-encoding
指定使用“分块”编码。使用分块编码,整个响应的长度是未指定的,并且响应被分块发送回,其中指定了每个块的大小。实际上,服务器缓冲来自 servlet 的输出。每当缓冲区填满时,就会发送另一个块。使用这种机制,HTTP 实际上可以开始流式传输无限长度的响应。
如果文件大于 2 Gb,则其大小不能表示为int
,因此在这种情况下,较旧的方法getContentLength()
将返回 -1。
使用 HEAD 请求,我让我的网络服务器回复正确的内容长度字段,否则该字段为空。我不知道这是否普遍有效,但就我而言,它确实有效:
private int tryGetFileSize(URL url) {
HttpURLConnection conn = null;
try {
conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("HEAD");
conn.getInputStream();
return conn.getContentLength();
} catch (IOException e) {
return -1;
} finally {
conn.disconnect();
}
}
您需要使用内容长度 (URLConnection.getContentLength())。不幸的是,这并不总是准确的,或者可能并不总是提供,因此依赖它并不总是安全的。
//URLConnection connection
private int FileSize(String url) {
// this is the method and it get the url as a parameter.
// this java class will allow us to get the size of the file.
URLConnection con;
// its in a try and catch incase the url given is wrong or invalid
try{
// we open the stream
con = new URL(url).openConnection()
return con.getContentLength();
}catch (Exception e){
e.printStackTrace();
// this is returned if the connection went invalid or failed.
return 0;
}
}
正如@erickson 所说,有时会有标题“Transfer-Encoding:chunked”,而不是“Content-Length:”,当然长度为空值。
关于 available() 方法——没有人能保证它会返回正确的值,所以我建议你不要使用它。