=====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 [[http://www.bbcbasic.co.uk/bbcwin/manual/bbcwine.html#urlmon|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