Content-Length 下载进度条
下载进度行为 情况 进度条 文本 有 Content-Length 按 0.1% 粒度平滑增长 0.0% → 100.0% 无 Content-Length 保持初始状态不变 正在下载... 完成 100% 下载完成 失败 不变 下载失败 Content-Length从服务端webserver传过来吗
是的,Content-Length 是 Web Server(服务端)通过 HTTP 响应头发送给客户端的。
例如客户端请求:
GET /file.zip HTTP/1.1
Host: example.com
服务器返回:
HTTP/1.1 200 OK
Content-Type: application/zip
Content-Length: 52428800
(二进制文件数据)
这里
Content-Length: 52428800
表示整个文件大小为 52,428,800 字节(约50MB)。
客户端下载时就可以计算:
进度 = 已下载字节数 / Content-Length * 100%
例如:
Content-Length = 1000000
收到100000字节
→ 10%
收到500000字节
→ 50%
收到1000000字节
→ 100%
没有 Content-Length 的情况
服务器也可以不发送 Content-Length。
例如:
HTTP/1.1 200 OK
Transfer-Encoding: chunked
4\r\n
Wiki\r\n
5\r\n
pedia\r\n
0\r\n
或者
HTTP/1.1 200 OK
(二进制数据一直发)
这种情况下客户端根本不知道还有多少数据。
因此:
收到100KB
↓
不知道总大小
↓
无法算百分比
只能显示:
正在下载...
或者
███████████>>>>>
这种不确定长度的动画。
WinHTTP 怎么获取 Content-Length
使用 WinHTTP 时,可以查询响应头:
DWORD dwSize = sizeof(DWORD);
DWORD contentLength = 0;
WinHttpQueryHeaders(
hRequest,
WINHTTP_QUERY_CONTENT_LENGTH | WINHTTP_QUERY_FLAG_NUMBER,
WINHTTP_HEADER_NAME_BY_INDEX,
&contentLength,
&dwSize,
WINHTTP_NO_HEADER_INDEX);
返回成功:
contentLength = 104857600
失败:
ERROR_WINHTTP_HEADER_NOT_FOUND
说明服务器没有发送 Content-Length。
为什么有时候没有 Content-Length?
常见原因包括:
- 启用了 Chunked(分块传输)
Transfer-Encoding: chunked
服务器边生成边发送数据,因此无法提前知道总长度。
- 动态生成内容
例如:
- PHP
- ASP.NET
- CGI
- Flask
- Node.js
页面是一边计算一边输出,长度无法预先确定。
- 实时数据流
例如:
- 摄像头视频流
- 日志流
- Server-Sent Events (SSE)
这些通常不会有固定结束长度。
- 服务器刻意不发送
有些 Web Server 或反向代理会移除 Content-Length,改用 Chunked 传输。
下载文件时一般都有吗?
对于普通文件下载(例如 .zip、.exe、.pdf),大多数 HTTP 服务器都会发送 Content-Length,因为文件大小是已知的。
例如:
- Apache HTTP Server
- Nginx
- Microsoft IIS
在提供静态文件下载时,通常都会返回:
Content-Length: xxxx
Accept-Ranges: bytes
因此下载器可以准确显示:
0.0%
15.6%
31.8%
...
99.9%
100.0%
建议你的下载进度逻辑
你的设计是比较合理的:
服务端是否返回 Content-Length | 进度条 | 文本 |
|---|---|---|
有 Content-Length |
按 (已下载字节 / Content-Length) 平滑更新到 100% |
0.0% → 100.0% |
无 Content-Length |
保持初始状态(或显示不确定进度动画) | 正在下载... |
| 下载完成 | 100% |
下载完成 |
| 下载失败 | 保持当前状态 | 下载失败 |
浙公网安备 33010602011771号