by Richard Russell, August 2007; amended July 2009

The simplest method of downloading a file (e.g. a web page) from an internet URL is to use the URLDownloadToFile API function as described in the main documentation. The following program segment illustrates how to do that:

      url$ = "http://www.bbcbasic.co.uk/bbcwin/bbcwin.html"
      file$ = @tmp$+"bbcwin.html"
      PROCurldownload(url$, file$)
      END
 
      DEF PROCurldownload(url$, file$)
      LOCAL urlmon%, res%
      SYS "LoadLibrary", "urlmon.dll" TO urlmon%
      SYS "GetProcAddress", urlmon%, "URLDownloadToFileA" TO `URLDownloadToFile`
      SYS `URLDownloadToFile`, 0, url$, file$, 0, 0 TO res%
      SYS "FreeLibrary", urlmon%
      IF res% ERROR 100, "Couldn't download "+url$
      ENDPROC
If you need to flush the cache to ensure you retrieve the latest version (e.g. it's a webcam picture) then it becomes slightly more complicated:

      url$ = "http://www.bbcbasic.co.uk/bbcwin/bbcwin.html"
      file$ = @tmp$+"bbcwin.html"
      PROCurldownloadflush(url$, file$)
      END
 
      DEF PROCurldownloadflush(url$, file$)
      LOCAL urlmon%, wininet%, res%
      SYS "LoadLibrary", "URLMON.DLL" TO urlmon%
      SYS "GetProcAddress", urlmon%, "URLDownloadToFileA" TO `URLDownloadToFile`
      SYS "LoadLibrary", "WININET.DLL" TO wininet%
      SYS "GetProcAddress", wininet%, "DeleteUrlCacheEntryA" TO `DeleteUrlCacheEntry`
      SYS `DeleteUrlCacheEntry`, url$
      SYS `URLDownloadToFile`, 0, url$, file$, 0, 0 TO res%
      SYS "FreeLibrary", wininet%
      SYS "FreeLibrary", urlmon%
      IF res% ERROR 100, "Couldn't download "+url$
      ENDPROC
These routines can be used for both HTTP and FTP downloads.

However under some circumstances the above methods do not work reliably. In that case you may find the following routine to be more successful:

      url$ = "http://www.bbcbasic.co.uk/bbcwin/bbcwin.html"
      file$ = @tmp$+"bbcwin.html"
      PROCurldownload(url$, file$)
      END
 
      DEF PROCurldownload(url$, file$)
      LOCAL wininet%, buffer%, hinet%, hreq%, file%, nbr%, nbw%, ok%
      DIM buffer% LOCAL 511
 
      _INTERNET_OPEN_TYPE_PRECONFIG = 0
      _INTERNET_FLAG_RELOAD = &80000000
 
      SYS "LoadLibrary", "WININET.DLL" TO wininet%
      SYS "GetProcAddress", wininet%, "InternetOpenA"       TO `InternetOpen`
      SYS "GetProcAddress", wininet%, "InternetOpenUrlA"    TO `InternetOpenUrl`
      SYS "GetProcAddress", wininet%, "InternetReadFile"    TO `InternetReadFile`
      SYS "GetProcAddress", wininet%, "InternetCloseHandle" TO `InternetCloseHandle`
 
      SYS `InternetOpen`, "BB4W", _INTERNET_OPEN_TYPE_PRECONFIG, 0, 0, 0 TO hinet%
      IF hinet% = 0 ERROR 100, "Couldn't open internet services"
 
      SYS `InternetOpenUrl`, hinet%, url$, "", 0, _INTERNET_FLAG_RELOAD, 0 TO hreq%
      IF hreq% = 0 THEN
        PROCinetcleanup
        ERROR 100, "Couldn't open "+url$
      ENDIF
 
      file% = OPENOUT(file$)
      IF file% = 0 THEN
        PROCinetcleanup
        ERROR 100, "Couldn't create "+file$
      ENDIF
 
      REPEAT
        SYS `InternetReadFile`, hreq%, buffer%, 512, ^nbr% TO ok%
        IF ok% = 0 THEN
          PROCinetcleanup
          ERROR 100, "Couldn't read from "+url$ 
        ENDIF
        SYS "WriteFile", @hfile%(file%), buffer%, nbr%, ^nbw%, 0 TO ok%
        IF ok% = 0 THEN
          PROCinetcleanup
          ERROR 100, "Couldn't write "+file$
        ENDIF
      UNTIL nbr% = 0
 
      CLOSE #file%
 
      PROCinetcleanup
      ENDPROC
 
      DEF PROCinetcleanup
      hreq% += 0  : IF hreq%  SYS `InternetCloseHandle`, hreq%  : hreq% = 0
      hinet% += 0 : IF hinet% SYS `InternetCloseHandle`, hinet% : hinet% = 0
      wininet% += 0 : IF wininet% SYS "FreeLibrary", wininet% : wininet% = 0
      ENDPROC
Unfortunately with early versions of Internet Explorer (pre 4.0) the above code results in a memory leak when used for http downloads (see http://support.microsoft.com/kb/174897). If you need your code to work with such old versions you can use the following routine instead (note that because the HTTP protocol is implied, you must not include the http:// in the supplied server$):

      server$ = "www.bbcbasic.co.uk"
      request$ = "bbcwin/bbcwin.html"
      file$ = @tmp$+"bbcwin.html"
      PROChttpdownload(server$, request$, file$)
      END
 
      DEF PROChttpdownload(server$, request$, file$)
      LOCAL wininet%, buffer%, hinet%, hsess%, hreq%, file%, nbr%, nbw%, ok%
      DIM buffer% LOCAL 511
 
      _INTERNET_OPEN_TYPE_PRECONFIG = 0
      _INTERNET_DEFAULT_HTTP_PORT = 80
      _INTERNET_SERVICE_HTTP = 3
      _INTERNET_FLAG_RELOAD = &80000000
 
      SYS "LoadLibrary", "WININET.DLL" TO wininet%
      SYS "GetProcAddress", wininet%, "InternetOpenA"       TO `InternetOpen`
      SYS "GetProcAddress", wininet%, "InternetConnectA"    TO `InternetConnect`
      SYS "GetProcAddress", wininet%, "HttpOpenRequestA"    TO `HttpOpenRequest`
      SYS "GetProcAddress", wininet%, "HttpSendRequestA"    TO `HttpSendRequest`
      SYS "GetProcAddress", wininet%, "InternetReadFile"    TO `InternetReadFile`
      SYS "GetProcAddress", wininet%, "InternetCloseHandle" TO `InternetCloseHandle`
 
      SYS `InternetOpen`, "BB4W", _INTERNET_OPEN_TYPE_PRECONFIG, 0, 0, 0 TO hinet%
      IF hinet% = 0 ERROR 100, "Couldn't open internet services"
 
      SYS `InternetConnect`, hinet%, server$, _INTERNET_DEFAULT_HTTP_PORT, \
      \                      "", "", _INTERNET_SERVICE_HTTP, 0, 0 TO hsess%
      IF hsess% = 0 THEN
        PROCinetcleanup
        ERROR 100, "Couldn't connect to "+server$
      ENDIF
 
      SYS `HttpOpenRequest`, hsess%, 0, request$, 0, 0, 0, _INTERNET_FLAG_RELOAD, \
      \                      0 TO hreq%
      IF hreq% = 0 THEN
        PROCinetcleanup
        ERROR 100, "Couldn't open "+request$
      ENDIF
 
      SYS `HttpSendRequest`, hreq%, 0, 0, 0, 0 TO ok%
      IF ok% = 0 THEN
        PROCinetcleanup
        ERROR 100, "Couldn't request "+request$
      ENDIF
 
      file% = OPENOUT(file$)
      IF file% = 0 THEN
        PROCinetcleanup
        ERROR 100, "Couldn't create "+file$
      ENDIF
 
      REPEAT
        SYS `InternetReadFile`, hreq%, buffer%, 512, ^nbr% TO ok%
        IF ok% = 0 THEN
          PROCinetcleanup
          ERROR 100, "Couldn't read "+request$
        ENDIF
        SYS "WriteFile", @hfile%(file%), buffer%, nbr%, ^nbw%, 0 TO ok%
        IF ok% = 0 THEN
          PROCinetcleanup
          ERROR 100, "Couldn't write "+file$
        ENDIF
      UNTIL nbr% = 0
 
      CLOSE #file%
 
      PROCinetcleanup
      ENDPROC
 
      DEF PROCinetcleanup
      hreq% += 0  : IF hreq%  SYS `InternetCloseHandle`, hreq%  : hreq% = 0
      hsess% += 0 : IF hsess% SYS `InternetCloseHandle`, hsess% : hsess% = 0
      hinet% += 0 : IF hinet% SYS `InternetCloseHandle`, hinet% : hinet% = 0
      wininet% += 0 : IF wininet% SYS "FreeLibrary", wininet% : wininet% = 0
      ENDPROC