当 HEAD 请求未报告 ContentLength 时,如何获取下载大小?
Posted
技术标签:
【中文标题】当 HEAD 请求未报告 ContentLength 时,如何获取下载大小?【英文标题】:How do I get the size of a download when a HEAD request doesn't report ContentLength? 【发布时间】:2013-08-22 14:24:25 【问题描述】:在 Delphi 中使用此代码获取网页大小:(我的意思是页面源大小)
uses
IdHTTP
function URLsize(const URL : string) : integer;
var
Http: TIdHTTP;
begin
Http := TIdHTTP.Create(nil);
try
Http.Head(URL);
result := round(Http.Response.ContentLength / 1048576); //MB
finally
Http.Free;
end;
end;
对于http://sample.com/test.exe
等一些 URL,我可以轻松获取文件大小。它以 MB 为单位返回大小。
但我无法使用此代码为http://***.com/
之类的 URL 获取 URL 大小;它返回0
或-1
。
在这种情况下如何获得尺寸?
【问题讨论】:
相关:***.com/questions/9165926/… 这就是为什么我说相关而不是重复。 当我使用您的确切函数测试http://***.com/
时,我得到 0 - 但不除以我得到 194569,它小于 1048576。这可能是你的问题吗?
Content-length 通常仅在下载文件(程序安装程序、DOC 和 PDF 等通用数据文件)时得到普遍支持。当涉及到文本数据时,通常不支持它(一直认为但只是检查过,SO 确实返回文本的内容长度),因此所涉及的函数通常会返回 -1。一个好的规则是不要期望来自 Web 服务器的内容长度并编写您的代码,因此这不是绝对必要的。
作为记录,昨天我下载了一些软件,虽然文件大小约为 10 MB,但谷歌浏览器没有显示预期的时间或完成百分比,因为它不知道有多大该文件是。服务器没有在标题中包含这个。尽管如此,Chrome 还是恭敬地下载了它,不管这个字段是什么。
【参考方案1】:
并非所有 HTTP HEAD 响应都包含内容长度。所以,一般来说,你想做的事情是不可能的。如果您遇到不包含内容长度的响应,您需要下载内容才能找到长度。
【讨论】:
但是像Internet Download Manager或Internet Download Accelerator这样的一些软件可以得到一个网页的大小。无需下载整个页面。他们是怎么做到的? @Sky:大卫是正确的。并非所有HEAD
请求(或GET
请求,就此而言)都可以提供Content-Length
标头(TIdHTTP.Response.HasContentLength
属性会告诉您标头是否存在)。这是在不下载实际文件的情况下获取文件大小的官方方法。如果下载管理器能够获得大小而您没有,那么管理器依赖于其他信息。您必须查看实际的HEAD
响应才能查看报告了哪些其他数据。不过,http://***.com/
确实有一个 Content-Length
标头。
如果 ***.com 确实为 HEAD 提供了内容长度,那么 Indy 肯定会传递它。
如果存在Content-Length
标头,Indy 确实会提供它。如果 ***(和其他服务器)预先知道文件总大小实际是多少,即使对于动态创建的内容,它们也可以提供 Content-Length
标头。它是在创建内容的同时发送内容,例如带有Transfer-Encoding: chunked
标头,其中Content-Length
要么不存在,因为在请求结束之前大小未知,要么存在但为0(甚至虽然它不应该存在,但有些服务器会这样做)。
再一次,如果 DM 正在获取文件大小而您没有,那么 DM 必须在查看其他内容,因此您需要查看完整的回复,看看您还能做什么看看。【参考方案2】:
即使网络服务器确实返回了正确的内容长度,您也需要将其除以1048576
以获得兆字节值。因为http://***.com/
远小于一个兆字节,所以它返回0
。但是,我仍然很难过您的-1
来自哪里-因为http://***.com/
为我返回194569
,没有分开。您是否从另一个网站获得了-1
?您的结果是来自Http.Response.ContentLength
的除值还是原始值?
【讨论】:
@jerryDodge 是的。因为大小小于兆字节,所以它返回 0。但我的问题是(我得到http://www.google.com/
的 -1
。)+ 使用上面的代码,当我得到 StackOveflow 的 content-length
时,它返回 196444
(不除它)。但是当我用浏览器加载站点并将页面源保存到文本文件时,文本大小为228154
。我不知道为什么。这有点令人困惑。
@Sky 那是因为元素是通过脚本动态添加到页面的。没有什么令人困惑的。下载原始文件 before 脚本开始添加它返回 194569,但 after 脚本添加了新内容,它大约变为 228154,这取决于动态加载的数据.
另外,*** 会不断进行更改,因此大小可能会在您的测试和我的测试等之后发生变化。以上是关于当 HEAD 请求未报告 ContentLength 时,如何获取下载大小?的主要内容,如果未能解决你的问题,请参考以下文章
当我使用 asmx 服务和 s-s-rS 报告服务时,我收到“请求失败,http 状态 401:未授权”