1. 概述
HTTP 协议提供了关于请求 Web 资源的全面信息。其头部字段之一 Content-Length
指定了资源的字节大小。我们可以通过 Java 的 URLConnection
类提取这些信息。
在下载前获取 Web 文件大小有助于估算所需网络流量。⚠️ 但需注意:服务器返回的大小值可能不准确,开发者可随意设置该字段值。
本教程将探讨如何使用 URLConnection
类的以下方法获取文件大小:
getContentLengthLong()
getHeaderField()
2. HTTP Content-Length 机制
Content-Length
头部字段直接表示响应体的字节大小。但需注意以下关键点:
✅ 基本原理:
HTTP 作为传输协议,通过头部字段描述响应属性,Content-Length
即表示响应体大小
❌ 两大限制:
- 当使用分块传输编码(
Transfer-Encoding: chunked
)时,无法预知文件总大小 - 服务器可能返回任意值(如 Spring 应用中开发者可手动设置),与实际文件大小不符
踩坑提醒:永远不要完全信任
Content-Length
值,它只是服务器声明的估算值
3. 文件大小获取方法对比
URLConnection
提供两种核心方法获取文件大小:
方法 | 返回类型 | 最大支持值 | 推荐场景 |
---|---|---|---|
getContentLength() |
int |
2 GiB | 已废弃 |
getContentLengthLong() |
long |
8 EiB | ✅ 首选 |
⚠️ 关键区别:
getContentLength()
无法处理超过Integer.MAX_VALUE
(2 GiB)的文件- 当
Content-Length
头部缺失时,两方法均返回 -1
// 错误示例:大文件会溢出
int size = connection.getContentLength(); // 危险!
// 正确做法:支持超大文件
long size = connection.getContentLengthLong(); // 安全
4. 使用 getContentLengthLong() 获取大小
以获取示例 PDF 文件(29,789 字节)为例:
String fileUrl = "https://www.ingka.com/wp-content/uploads/2020/11/dummy.pdf";
URL url = new URL(fileUrl);
URLConnection urlConnection = url.openConnection();
long fileSize = urlConnection.getContentLengthLong();
if (fileSize != -1) {
assertEquals(29789, fileSize);
} else {
fail("无法确定文件大小");
}
执行流程:
- 创建
URL
对象指向目标文件 - 通过
openConnection()
建立连接 - 调用
getContentLengthLong()
获取大小 - 处理返回值(-1 表示失败)
5. 使用 getHeaderField() 替代方案
直接读取 HTTP 头部字段是更底层的实现方式:
@Test
void givenUrl_whenGetFileSizeUsingURLConnectionAndGetHeaderField_thenCorrect() throws IOException {
URL url = new URL(fileUrl);
URLConnection urlConnection = url.openConnection();
String headerField = urlConnection.getHeaderField("Content-Length");
if (headerField != null && !headerField.isEmpty()) {
long fileSize = Long.parseLong(headerField);
assertEquals(29789, fileSize);
} else {
fail("无法确定文件大小");
}
}
关键步骤:
- 通过
getHeaderField("Content-Length")
获取原始字符串值 - 将字符串转换为
long
类型 - 处理空值情况(头部缺失时返回
null
)
简单粗暴:本质是手动解析 HTTP 头部,与
getContentLengthLong()
效果相同
6. 总结
获取 Web 文件大小的核心要点:
✅ 推荐方法:
long size = new URL("https://example.com/file.zip")
.openConnection()
.getContentLengthLong();
❌ 注意事项:
- 返回 -1 表示无法获取大小(头部缺失或分块传输)
- 服务器可能返回错误的大小值
- 大文件(>2 GiB)必须使用
getContentLengthLong()
完整示例代码见 GitHub 仓库。