Delphi使用Indy、ICS组件读取网页

使用Indy 10中TIdHTTP的例子:

代码

uses
  IdHttp;
.
.
.
function HttpGet(const Url: string; var Html: string): Boolean;
var
  HttpClient: TIdHTTP;
begin
  Result := False;
  HttpClient := TIdHTTP.Create(nil);
  try
    Html := HttpClient.Get(Url);
    Result := True;
  except
    on e: Exception do
    begin
    end;
  end;
  HttpClient.Free;
end;

Indy采用的是同步I/O的方式,而且在连接超时控制方面存在bug,因此TIdHttp.Get()有时会发生陷入死锁无法返回的问题。

使用ICS中THttpCli的例子:

uses
  HttpProt;
.
.
.
function HttpGet(const Url: string; var Html: string): Boolean;
var
  HttpClient: THttpCli;
  DataLen: Int64;
  FailMsg: string;
begin
  Result := False;
  HttpClient := THttpCli.Create(nil);
  HttpClient.URL := Url;
  HttpClient.NoCache := True;
  HttpClient.RcvdStream := TMemoryStream.Create;
  try
    try
      HttpClient.Get;
      DataLen := HttpClient.RcvdStream.Size;
      SetLength(Html, DataLen);
      HttpClient.RcvdStream.Position := 0;
      HttpClient.RcvdStream.Read(PChar(Html)^, DataLen);
      Result := True;
    except
      on E: EHttpException do
      begin
        FailMsg := Format('Failed : %d %s',
          [HttpClient.StatusCode, HttpClient.ReasonPhrase]);
      end else
        raise;
    end;
  finally
    HttpClient.RcvdStream.Free;
    HttpClient.RcvdStream := nil;
    HttpClient.Free;
  end;
end;

ICS使用的是异步I/O,其TFtpClient组件有Timout属性可以对连接超时进行控制,而THttpCli组件没有。但可以采用在定时器中调用THttpCli.Abort()取消连接的方式控制超时,也可以显式调用异步方法:

var
 
  HttpClient: THttpCli;
 
  DataLen: Int64;
 
  FailMsg: string;
 
  Tick: Cardinal;
 
begin
 
  Result := False;
 
  HttpClient := THttpCli.Create(nil);
 
  HttpClient.URL := Url;
 
  HttpClient.NoCache := True;
 
  HttpClient.RcvdStream := TMemoryStream.Create;
 
  Tick := GetTickCount;
 
  try
 
    try
 
      HttpClient.GetASync;
 
      while HttpClient.State <> httpReady do //检测HTTP状态
 
      begin
 
        if GetTickCount - Tick > 30*1000 then //此处设置了30S超时,可根据需要修改此数值
 
        begin
 
          HttpClient.Abort;
 
          Exit;
 
        end;
 
        Application.ProcessMessages;
 
      end;
 
      DataLen := HttpClient.RcvdStream.Size;
 
      SetLength(Html, DataLen);
 
      HttpClient.RcvdStream.Position := 0;
 
      HttpClient.RcvdStream.Read(PChar(Html)^, DataLen);
 
      Result := True;
 
    except
 
      on E: EHttpException do
 
      begin
 
        FailMsg := Format('Failed : %d %s',
 
          [HttpClient.StatusCode, HttpClient.ReasonPhrase]);
 
      end else
 
        raise;
 
    end;
 
  finally
 
    HttpClient.RcvdStream.Free;
 
    HttpClient.RcvdStream := nil;
 
    HttpClient.Free;
 
  end;
 
end