download a file over http

From Free Pascal wiki

Introduction

Downloading a file from the internet is a recurring question on the forums. And the answers are very easy and all of them just as good.
Here I will present you some small but complete examples on how to download a file using the three most used libraries for Pascal and Curl, which is also cross-platform.
Best thing is: these are all cross-platform.

  • Fcl-web
  • Synapse
  • Indy
  • Curl

Fcl-web

Fcl-web has a very powerful TFPHttpClient class. It takes just a few lines of code (one) for our download program to work. Fcl-web is very well maintained by the FPC core development team.

Let's show you the simplest example using HTTP only. This example retrieves just an html page and writes it to the screen.

It uses one of the class Get methods of TfpHttpClient. You don't need to create and free the class. There are several overloads for e.g. TStrings or TStream (file) as well:

program dl_fphttp_a;
{$mode delphi}{$ifdef windows}{$apptype console}{$endif}
uses 
  fphttpclient;
begin  
  writeln(TFPHttpClient.SimpleGet('http://example.com')); 
end.

That's all! For simple purposes this will suffice. You can even use it for HTTPS, which needs just the inclusion of two units:

program dl_fphttp_b;
{$mode delphi}{$ifdef windows}{$apptype console}{$endif}
uses 
  fphttpclient, fpopenssl, openssl;
begin  
  writeln(TFPHttpClient.SimpleGet('https://freepascal.org')); 
end.

This really is all there is to do in simple scenarios, usually if you have enough control.

But there are some caveats with this code. The foremost one being that this code does not allow for redirects. Let me demo that:

program dl_fphttp_redirect_error;
{$mode delphi}{$ifdef windows}{$apptype console}{$endif}
uses 
  sysutils, fphttpclient, fpopenssl, openssl;
begin  
  try
    writeln(TFPHttpClient.SimpleGet('https://google.com')); 
  except on E:EHttpClient do
    writeln(e.message) else raise;
  end;
end.

Because the Google URL uses redirects, there is an exception: "Unexpected response status code: 301". In such a case we need more control, which I will show you in the next example:

program dl_fphttp_c;
{$mode delphi}{$ifdef windows}{$apptype console}{$endif}
uses
  classes, fphttpclient, fpopenssl, openssl;
var
  Client: TFPHttpClient;
begin
  { SSL initialization has to be done by hand here }
  InitSSLInterface;
  Client := TFPHttpClient.Create(nil);
  try
    { Allow redirections }
    Client.AllowRedirect := true;
    writeln(Client.Get('https://google.com/')); 
  finally
    Client.Free;
  end;
end.

You see this requires slightly more code, but it is still a very small program. Well, now we go to the last example, which downloads any file and saves it to disk.

You can use it as a template for your own code, it demonstrates almost everything you need.

program dl_fphttp_d;
{$mode delphi}{$ifdef windows}{$apptype console}{$endif}
uses
  sysutils, classes, fphttpclient, fpopenssl, openssl;
const
  Filename = 'testdownload.txt';
var
  Client: TFPHttpClient;
  FS: TStream;
  SL: TStringList;
begin
  { SSL initialization has to be done by hand here }
  InitSSLInterface;
  Client := TFPHttpClient.Create(nil);
  FS := TFileStream.Create(Filename,fmCreate or fmOpenWrite);
  try
    try
      { Allow redirections }
      Client.AllowRedirect := true;
      Client.Get('https://google.com/',FS); 
    except
      on E: EHttpClient do
        writeln(E.Message)
      else
        raise;
    end;
  finally
    FS.Free;
    Client.Free;
  end;
  
  { Test our file }
  if FileExists(Filename) then
  try
    SL := TStringList.Create;
    SL.LoadFromFile(Filename);
    writeln(SL.Text);
  finally
    SL.Free;
  end;      
end.

Synapse

TODO

Indy

TODO

Curl

TODO