=====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