How to download a web page into a variable?

Using Indy:

uses IdHTTP;

const
  HTTP_RESPONSE_OK = 200;

function GetPage(aURL: string): string;
var
  Response: TStringStream;
  HTTP: TIdHTTP;
begin
  Result := '';
  Response := TStringStream.Create('');
  try
    HTTP := TIdHTTP.Create(nil);
    try
      HTTP.Get(aURL, Response);
      if HTTP.ResponseCode = HTTP_RESPONSE_OK then begin
        Result := Response.DataString;
      end else begin
        // TODO -cLogging: add some logging
      end;
    finally
      HTTP.Free;
    end;
  finally
    Response.Free;
  end;
end;

Using the native Microsoft Windows WinInet API:

function WebGetData(const UserAgent: string; const URL: string): string;
var
  hInet: HINTERNET;
  hURL: HINTERNET;
  Buffer: array[0..1023] of AnsiChar;
  BufferLen: cardinal;
begin
  result := '';
  hInet := InternetOpen(PChar(UserAgent), INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
  if hInet = nil then RaiseLastOSError;
  try
    hURL := InternetOpenUrl(hInet, PChar(URL), nil, 0, 0, 0);
    if hURL = nil then RaiseLastOSError;
    try
      repeat
        if not InternetReadFile(hURL, @Buffer, SizeOf(Buffer), BufferLen) then
          RaiseLastOSError;
        result := result + UTF8Decode(Copy(Buffer, 1, BufferLen))
      until BufferLen = 0;
    finally
      InternetCloseHandle(hURL);
    end;
  finally
    InternetCloseHandle(hInet);
  end;
end;

Try it:

procedure TForm1.Button1Click(Sender: TObject);
begin
  Memo1.Text := WebGetData('My Own Client', 'http://www.bbc.co.uk')
end;

But this only works if the encoding is UTF-8. So, to make it work in other cases, you either have to handle these separately, or you can use the Indy high-level wrappers, as suggested by Marjan. I admit they are superior in this case, but I still want to promote the underlying API, if for no other reason than educational...

Tags:

Delphi