This is an old revision of the document!
Downloading a file from a URL
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