For a CLI tool I'm working on I needed a way to download a file and show progress.
Using UrlDownloadToFile with a callback is a convoluted mess and I gave up on that approach. Plus you need to use COM for it to work.
Anyway, I rolled my own which turned out to be fairly easy,
Dim Source$
$pragma comment(lib, "wininet.lib")
' ~629MB Test File, Debian ISO
Source$ = "https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/debian-12.5.0-amd64-netinst.iso"
DownloadWithProgress(Source$)
Pause
Sub DownloadWithProgress(url$)
Dim As HINTERNET hInternet, hUrl
Dim szSize$, filename$, Dest$[20]
Dim As DWORD dwBytesRead, dwPercentage
Dim bRead as BOOL, bufferSize, contentSize, cnt
dim pBuffer[BCXSTRSIZE] as Byte
cnt = Split(Dest$,url$,"/")
filename$ = Dest$[cnt-1]
hInternet = InternetOpen("Mozilla/5.0", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0)
if hInternet = Null then print "InternetOpen Failed", GetLastError(): End = 1
hUrl = InternetOpenUrl(hInternet, url$, NULL, 0, INTERNET_FLAG_RELOAD, 0)
if hUrl = Null then
print "InternetOpenUrl Failed", GetLastError()
InternetCloseHandle(hInternet)
End = 1
End If
contentSize = getContentSize(hUrl)
OPEN filename$ FOR Binary New AS FP1
Color 11,0 : Print E"\n Downloading ", filename$,"...\n" : Color 7,0
While True
bRead = InternetReadFile( hUrl, pBuffer, sizeof(pBuffer), &dwBytesRead)
If dwBytesRead = 0 then Exit While
If Not bRead Then
Print "InternetReadFile error : ", GetLastError()
Close FP1 : CloseConnections(2,hUrl,hInternet)
End = 1
End If
bufferSize += dwBytesRead
dwPercentage = Round((double)bufferSize / contentSize * 100,0)
szSize$ = convertFromBytes(bufferSize)
Color 14,0
Print E"\r", dwPercentage, "% [", rpad$(repeat$(dwPercentage / 2, chr$(177)), 50),"]",bufferSize / 1048576, szSize$, " of", contentSize / 1048576, "MB ";
Color 7,0
put$ FP1, pBuffer, sizeof(pBuffer)
Wend
Close FP1
CloseConnections(2,hUrl,hInternet)
End Sub
Sub CloseConnections(i%,...)
Dim As HINTERNET handle
Dim As va_list ap
va_start(ap, i%)
For integer cnt = 0 To i% -1
handle = va_arg(ap,HINTERNET)
InternetCloseHandle(handle)
Next
va_end(ap)
End Sub
Function convertFromBytes(bufSize%) As String
Dim szSize$
Select Case bufSize%
Case < 1024
szSize$ = "Bytes"
Case < 1048576
szSize$ = "KB"
Case Else
szSize$ = "MB"
End Select
Return szSize$
End Function
Function getContentSize(hUrl as HINTERNET) as Integer
Dim As Dword dwSize=BCXSTRSIZE
Dim szContentLength$, contentSize
HttpQueryInfo(hUrl, HTTP_QUERY_CONTENT_LENGTH, szContentLength$, &dwSize, NULL)
contentSize = (int)Val(szContentLength)
Return contentSize
End Function
See attached screenshot to see it in action...
AIR.