为什么有些下载文件不知道自己的大小?[重复]


82

这个问题已经在这里有了答案:

有时,在网络浏览器中下载文件时,下载进度不会“知道”文件的总大小,也不知道下载的过程;它只是显示文件的下载速度,总计为“未知”。

浏览器为什么不知道某些文件的最终大小?它首先从何处获得此信息?


13
动态创建的文件没有大小,它们会以流的形式出现,直到达到EOF。
Fiasco Labs

Answers:


114

要从Web服务器请求文档,浏览器使用HTTP协议。您可能从地址栏中知道该名称(现在可能已经隐藏了,但是当您单击地址栏时,复制URL并将其粘贴到某些文本编辑器中,您会http://在开头看到)。HTTP是一个简单的基于文本的协议。它是这样的:

首先,您的浏览器连接到网站的服务器,并发送要下载的文档的URL(网页也是文档)以及有关浏览器本身的一些详细信息(User-Agent等)。例如,要在SuperUser网站上加载主页http://superuser.com/,我的浏览器会发送如下请求:

GET / HTTP/1.1
Host: superuser.com
Connection: keep-alive
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.0 Safari/537.36
Accept-Encoding: gzip,deflate,sdch
Accept-Language: pl-PL,pl;q=0.8,en-US;q=0.6,en;q=0.4
Cookie: [removed for security]
DNT: 1
If-Modified-Since: Tue, 09 Jul 2013 07:14:17 GMT

第一行指定服务器应返回的文档。其他行称为标题;他们看起来像这样:

Header name: Header value

这些行发送其他信息,以帮助服务器确定要做什么。

如果一切正常,服务器将通过发送请求的文档进行响应。响应从状态消息开始,然后是一些标题(包含有关文档的详细信息),最后,如果一切正常,则返回文档的内容。这是超级用户服务器对我的请求的答复如下:

HTTP/1.1 200 OK
Cache-Control: public, max-age=60
Content-Type: text/html; charset=utf-8
Expires: Tue, 09 Jul 2013 07:27:20 GMT
Last-Modified: Tue, 09 Jul 2013 07:26:20 GMT
Vary: *
X-Frame-Options: SAMEORIGIN
Date: Tue, 09 Jul 2013 07:26:19 GMT
Content-Length: 139672

<!DOCTYPE html>
<html>
    [...snip...]
</html>

在最后一行之后,SuperUser的服务器关闭连接。

第一行(HTTP/1.1 200 OK)包含响应代码,在本例中为200 OK。这意味着服务器已决定可以根据请求返回文档,并保证其后的内容将是这样的文档。如果不是这种情况,那么代码将是其他代码,它将提供一些指示服务器不只是返回文档作为响应的原因:例如,如果找不到所需的文档,则应该返回404 Not Found,并且如果不允许您访问有问题的内容,它应该返回403 Forbidden

在第一条状态行之后,是响应头。他们提供有关返回内容的更多信息,例如Content-type

接下来是一个空行。它表明以下事实:不再有响应头。该行之后的所有内容都是其请求的文档的内容。因此,在上面的示例中,<!DOCTYPE html>是SuperUser主页(HTML文档)的第一行。如果我要下载文档,可能是一些乱码,因为大多数文档格式未经事先处理就无法读取。

返回标题。对我们来说最有趣的是最后一个Content-Length。它通知浏览器在空行之后应该有多少字节的数据,因此基本上是用字节表示的文档大小。此标头不是必需的,服务器可以省略。有时无法预测文档的大小(例如,动态生成文档时),有时懒惰的程序员不包含它(在驱动程序下载站点上很常见),有时网站由不知道的新手创建这样的标题。

无论如何,无论原因是什么,标题都可能丢失。在那种情况下,浏览器不知道服务器将要发送多少数据,因此将文档大小显示为unknown,等待服务器关闭连接。这就是文档大小未知的原因。


4
一个非常非常小的注释:浏览器支持HTTP以外的协议。但是,如今其他协议很少见,即使细节有所不同,基本上相同的概念也适用于其他协议。
罗伯·费舍尔

5
@RobertFisher FTP是一种罕见的协议吗?:p
Thomas

5
@Thomas这是我最近的经历。自从我记得在浏览器中看到ftp URL已有好几年了。几年前,我在工作中直接使用ftp而不是使用浏览器(几乎完全是上载),但是这些任务现在由scp处理。我今天使用ftp的唯一一件事就是将内容上传到简约的Web主机。当然是YMMV。^ _ ^
罗伯·费舍尔

2
这正是使我喜欢这个网站的答案。如何授予赏金?
巴西那家伙

1
您的@ ruda.almeida对此表示不同意,您可以在meta.superuser.com上发布有关它的信息,将对其进行讨论,也许有人会重新提出问题。
gronostaj

54

HTTP Content-Length标头在某些情况下是可选的,因此它可能不会与文件一起发送;当套接字关闭时,将指示文件的末尾。


1
确切地说,HTTP 1.0通过在每个文档后关闭套接字来定义内容长度。HTTP 1.1仍支持此功能以实现兼容性。但是,如果使用Content-Length标头字段或使用传输了文档,则HTTP 1.1允许为多个文档重用连接Transfer-Encoding: chunked。后者允许动态生成内容,并在生成内容时分段发送它,并能够用信号通知文档的结尾。
2013年

3

快速创建内容(例如.pdf文档或Excel工作表)时,大小是无法得知的。在这种情况下,服务器无法向您发送下载大小,并且浏览器也无法显示总大小。


9
@alfo不得不不同意……如果我正在流传输视频,或者即使我正在流传输的大小不是固定大小的任何数据,那么关键是要尽快将数据提供给用户,我将不知道开始传输时的大小
Foon

4
@Alfo您可以动态创建.pdf文件之类的数据。只要数据没有竞争性地写入,您就不知道大小,但是您可以将ata已经发送到浏览器。我已经用Java完成了此操作,并向浏览器发送了动态生成的Excel文件。从浏览器的角度看,它看起来像是下载,但从服务器的角度看,它是流媒体。因此,即使您无法想象,也可以流式传输 .pdf文件。在浏览器中,它看起来像是没有已知长度的下载。
Uwe Plonus

8
@Alfo-它仅需要在最后一个数据包发送到客户端之前完成创建。
GalacticCowboy

4
@Alfo我从没考虑过视频流传输,但一般来说都涉及流传输,它也可以流传输.pdf文件或Excel工作表!
Uwe Plonus

2
@Alfo-您有一个有效的论点,可以先在内存中完全创建动态文件,然后再通过HTTP发送动态文件,动态文件易于计算内容长度。但是,如果服务器正在发送许多将动态创建的大型文件,这些文件将被分解为许多数据包,那么服务器就应该在发送计算出的块时才开始发送块(相对于必须在内存中创建每个大文件然后发送)。HTTP 1.1 为此专门设计了分块传输编码
jimbob博士2013年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.