title: How to retrieve a file from Internet via HTTP?
body: <p>I want to download a file from Internet and InternetReadFile seem a good and easy solution at the first glance. Actually, too good to be true. Indeed, digging a bit I have started to see that actually there are a lot of issues with it. People are complaining about all kinds of problems when using this code. </p>
  
  <p>Problems could appear because:</p>
  
  <ul>
  <li>the application freezes temporarily until the HTTP server responds</li>
  <li>the application freezes temporarily because the Internet connections breaks</li>
  <li>the application locks up because the HTTP server never responds</li>
  <li>the InternetOpen (I just discovered this recently) MUST be called only once during application life time</li>
  </ul>
  
  <p>I could not find a complete example about how to use it properly and robustly. Does anybody have an idea about how to implement it in a separate thread and with a time out? There is another SIMPLE way to robustly download a file from Internet. Though I don't want to complicate my life with very large libraries like Jedi or even Indy.</p>
  
  <pre><code>function GetFileHTTP (const fileURL, FileName: String): boolean;
  CONST
    BufferSize = 1024;
  VAR
    hSession, hURL: HInternet;
    Buffer: array[1..BufferSize] of Byte;
    BufferLen: DWORD;
    f: File;
    sAppName: string;
  begin
  //  result := false;
   sAppName := ExtractFileName(Application.ExeName) ;
   hSession := InternetOpen(PChar(sAppName), INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0) ;  { be aware that InternetOpen  need only be called once in your application!!!!!!!!!!!!!! }
   TRY
    hURL := InternetOpenURL(hSession, PChar(fileURL), nil, 0, 0, 0) ;
    TRY
     AssignFile(f, FileName) ;
     Rewrite(f, 1) ;
     REPEAT
      InternetReadFile(hURL, @Buffer, SizeOf(Buffer), BufferLen);
      BlockWrite(f, Buffer, BufferLen)
     UNTIL BufferLen = 0;
     CloseFile(f) ;
     Result:= True;
    FINALLY
     InternetCloseHandle(hURL)
    end
   FINALLY
    InternetCloseHandle(hSession)
   END;
  END;
  </code></pre>
  
  <p>Edit:
  This functions checks if Internet connection is available. It seems to work on Win98 also.</p>
  
  <pre><code>{  Are we connected to the Internet? }
  function IsConnectedToInternet: Boolean;                                        { Call SHELL32.DLL for Win &lt; Win98 otherwise call URL.dll }
  var InetIsOffline: function(dwFlags: DWORD): BOOL; stdcall;
  begin
   Result:= FALSE;
   if IsApiFunctionAvailable('URL.DLL', 'InetIsOffline', @InetIsOffline)
   then Result:= NOT InetIsOffLine(0)
   else
     if IsApiFunctionAvailable('SHELL32.DLL', 'InetIsOffline', @InetIsOffline)
     then Result:= NOT InetIsOffLine(0)
  end;
  </code></pre>
  
  <p>I am using Delphi 7. Many thanks.</p>
  
  <hr>
  
  <p>Edit:</p>
  
  <p>Losing customers because the application hangs at the first start up is the perfect recipe for losing money.</p>
  
  <p>Writing your code to be Microsoft platform dependent is bad. You never know if the customer has the IE version x.x installed.</p>
  
  <p>Installing stuff into a user's computer is like playing with guns. It will backfire.</p>
  
  <p>(see more about this here: <a href="http://thesunstroke.blogspot.com/2010/06/programmig-like-there-is-no-ms-windows.html" rel="nofollow noreferrer">http://thesunstroke.blogspot.com/2010/06/programmig-like-there-is-no-ms-windows.html</a>)</p>