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