当 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 ManagerInternet 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:未授权”

http 500 内部服务器错误,,两种浏览器显示的错误报告,请求帮组

jmeter中脚本数据分离并生成报告

Jmeter(一)压测入门及结果报告分析

当 HEAD 请求失败时,Gradle 无法下载依赖项

百度统计调研报告