我正在为学校做一个项目,我正在实现一个可以用来从网上下载文件的工具(有一个限制选项).问题是,我将拥有一个GUI,我将使用一个JProgressBar
小部件,我想展示当前的下载进度.为此,我需要知道文件的大小.如何在下载文件之前获取文件的大小.
任何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()方法.
如上所述,URLConnection getContentLengthLong()
是你最好的选择,但它并不总能给出明确的长度.那是因为HTTP协议(以及其他可以用a表示的URLConnection
)并不总是传达长度.
在HTTP的情况下,通常不知道动态内容的长度 - 当content-length
正常发送报头时.相反,另一个标头transfer-encoding
指定使用"分块"编码.对于分块编码,未指定整个响应的长度,并且响应被分段发回,其中指定了每个片段的大小.实际上,服务器缓冲来自servlet的输出.每当缓冲区填满时,就会发送另一个块.使用这种机制,HTTP实际上可以开始流式传输无限长度的响应.
如果文件大于2 Gb,则其大小不能表示为a 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(); } }