使用Delphi编程,从远程文件获取文件大小,然后再下载。

7

在使用Delphi下载远程文件之前,我如何确定它的大小(以字节为单位)?

提前感谢。


你打算如何下载它,使用http/ftp等方式? - Re0sless
3个回答

12

你可以使用Indy。

首先包含 IdHTTP

你可以通过以下方式检索大小:

procedure TFormMain.Button1Click(Sender: TObject);
var
  Http: TIdHTTP;
begin
  Http := TIdHTTP.Create(nil);
  try
    Http.Head('http://live.sysinternals.com/ADExplorer.exe');

    ShowMessage(IntToStr(Http.Response.ContentLength));
  finally
    Http.Free;
  end;
end;

11

简短回答:使用HTTP HEAD命令,该命令可在Indy Delphi的TIdHttp组件中获得。

细节:

HTTP协议定义了一个HEAD方法。

9.4 HEAD

HEAD方法与GET方法相同,除了服务器不能返回响应消息体。与对GET请求的响应中所发送的信息相同,响应头中包含的元信息也应该是相同的。该方法可以用于获取有关所请求实体的元信息,而不必传输实体本身。该方法通常用于测试超文本链接的有效性、可访问性和最近修改记录。

对HEAD请求的响应可能是可缓存的,因为响应中包含的信息可能会用于从该资源更新先前缓存的实体。如果新字段值表明缓存的实体与当前实体不同(如通过Content-Length、Content-MD5、ETag或Last-Modified的更改所指示的那样),则缓存必须将缓存条目视为过期的。

HEAD请求的响应与GET请求的响应相同,但没有响应体,检索完整的响应头,而不是整个内容。

检索到的HTTP响应头在Wikipedia的HTTP headers列表中有文档记录。 http://en.wikipedia.org/wiki/List_of_HTTP_headers

HTTP头是HTTP请求的核心,并且在HTTP响应中非常重要。它们定义了所请求的数据或已提供的数据的各种特征。HTTP头与请求或响应主题由一个空行分隔。HTTP头可以是任意字符串,但只有一些是常见理解的。

对于用于检索内容的有效URL,始终存在一个标题,即Content-Length标题。

14.13 Content-Length

Content-Length实体头字段指示发送给接收者的实体正文的OCTET十进制数大小,或在HEAD方法的情况下,如果该请求为GET,则发送的实体正文大小。

Content-Length = "Content-Length" ":" 1*DIGIT

一个示例是

Content-Length: 3495

除非在第4.4节中的规则禁止这样做,否则应用程序应使用此字段来指示消息正文的传输长度。

任何大于或等于零的Content-Length值都是有效的。第4.4节描述如何确定消息正文的长度,如果没有给出Content-Length。

请注意,该字段的含义在MIME中与相应的定义显着不同,在MIME中它是一个可选字段,用于“message/external-body”内容类型中。在HTTP中,除非第4.4节的规则禁止这样做,否则应在能够在传输之前确定消息长度的情况下发送。

从Delphi中,将TIdHttp组件拖到您的窗体中。然后将以下代码粘贴到您的Delphi事件处理方法之一中。

var 
  url: string;  // must contain a fully qualified url
  contentLength: integer;
begin
  ....
  contentLength:=0;
  try
    Idhttp1.Head(url);
    contentLength:=idhttp1.response.ContentLength;
  except end;
  ....

3
请注意,并非所有服务器都会返回head请求的有效内容大小。如果内容长度为0,则只有发出GET请求才能确定。例如,对Google标志的HEAD请求返回0个内容长度,但GET请求返回正确的长度,但也检索到图像。一些服务器将content-length返回为header后面数据包的长度。
您可以使用Synapse来获取此信息。请注意,数据已传输,但缓冲区被丢弃。这是一种更可靠的方法,但需要额外的带宽。
var
  HTTP : tHTTPSend;
begin
  HTTP := THTTPSend.Create;
  try
    HTTP.HTTPMethod('GET',url);
    DownloadSize := HTTP.DownloadSize;
  finally
    HTTP.Free;
  end;
end;

这实际上是两个答案。第一部分很有用,有些 Web 服务器存在这种错误行为,尽管这违反了 HTTP 协议定义。(2)第二部分没有用,因为问题是“如何在下载之前确定大小”;所以在这里下载数据不是一个有效的替代方案。 - PA.
这并不算是错误行为。有些服务器不能以单个字节流的形式传递数据,例如动态生成的数据。在这种情况下(即:当“传输编码”标头包含“分块”时),数据大小根本无法提前知道。 - Remy Lebeau
@Remy:没错,在某些情况下,比如动态流媒体和“分块”编码,这种行为是正确的。但是,谷歌标志的例子无疑是一种错误行为。 - PA.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接