Credits to V2 for writing the original source here http://www.purebasic.fr/english/viewtopic.php?t=8331.
Edit: Updated the code to thread the download, and you can stop the download process. Supports one simultaneous download without freezing up the form any.
Code: Select all
Global StopDownload.l = 0
Enumeration
#Window
#Start
#ProgressBar
#Frame
#Label
#Label2
#URL
EndEnumeration
Structure DownloadData
Folder.s
File.s
URL.s
EndStructure
Procedure DoEvents()
msg.MSG
If PeekMessage_(msg, 0, 0, 0, 1)
TranslateMessage_(msg)
DispatchMessage_(msg)
Else
Delay(1)
EndIf
EndProcedure
Procedure DownloadWithProgress(*Parameters.DownloadData)
Protected.l FileBytes = 0, Bytes = 0, INTERNET_FLAG_RELOAD = $80000000, Size, Buffer = 4096, LastSize, Timer, Timed
Protected.b isLoop = 1, OpenType = 1
Protected.s Header, Line
;Get Filesize
Header = GetHTTPHeader(*Parameters\URL)
Repeat
x + 1
Line = StringField(Header, x, Chr(10))
Until FindString(Line, "Content-Length:", 1, #PB_String_NoCase)
Size = Val(StringField(Line, 2, "Content-Length: "))
;Allocate Buffer For File Data
*Memory = AllocateMemory(Buffer)
;Create File To Dump Data To And Initialize WinINet
Result = CreateFile(1, *Parameters\Folder + *Parameters\File)
hInet = InternetOpen_("", OpenType, #Null, #Null, 0)
hURL = InternetOpenUrl_(hInet, *Parameters\URL, #Null, 0, INTERNET_FLAG_RELOAD, 0)
If Size > 1048576
SetGadgetText(#Label, "File Size: "+Str(Size/1048576)+" MB")
ElseIf Size > 1024
SetGadgetText(#Label, "File Size: "+Str(Size/1024)+" KB")
Else
SetGadgetText(#Label, "File Size: "+Str(Size)+" Bytes")
EndIf
SetGadgetAttribute(#ProgressBar, #PB_ProgressBar_Maximum, Size)
;Start Downloading
Timer = ElapsedMilliseconds()
Repeat
InternetReadFile_(hURL, *Memory, Buffer, @Bytes)
If Bytes = 0
isLoop = 0
Else
FileBytes = FileBytes + Bytes
Timed = ElapsedMilliseconds()-Timer
If Timed > 1000
SetGadgetText(#Label2, "Download Speed: "+Str((FileBytes - LastSize)/1024)+" KB/s")
Timer = ElapsedMilliseconds()
LastSize = FileBytes
EndIf
If Size >= FileBytes : SetGadgetState(#ProgressBar, FileBytes) : EndIf
If StopDownload = 1 : isLoop = 0 : StopDownload = 0 : EndIf
WriteData(1, *Memory, Bytes)
EndIf
DoEvents()
Until isLoop = 0
;Release Handles
InternetCloseHandle_(hURL)
InternetCloseHandle_(hInet)
CloseFile(1)
;Form Clean
SetGadgetState(#ProgressBar, 0)
SetGadgetText(#Label, "File Size: ")
SetGadgetText(#Label2, "Download Speed: ")
SetGadgetText(#Start, "Start")
;Clean Up
FreeMemory(*Memory)
ClearStructure(*Parameters, DownloadData)
FreeMemory(*Parameters)
EndProcedure
InitNetwork()
If OpenWindow(#Window, 0, 0, 400, 175, "Download With Progress", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
StringGadget(#URL, 10, 10, 380, 20, "http://ddj9plya1d2mr.cloudfront.net/ubuntu-13.04-desktop-amd64.iso")
ProgressBarGadget(#ProgressBar, 10, 40, 380, 30, 0, 100, #PB_ProgressBar_Smooth)
TextGadget(#Label, 10, 80, 300, 20, "File Size:")
TextGadget(#Label2, 10, 100, 300, 20, "Download Speed:")
Frame3DGadget(#Frame, -10, 120, 420, 110, "")
ButtonGadget(#Start, 280, 140, 110, 25, "Start", #PB_Button_Default)
Repeat
EventID = WaitWindowEvent()
Select EventID
Case #PB_Event_Gadget
Select EventGadget()
Case #Start
If IsThread(Thread)
StopDownload = 1
Else
URL.s = GetGadgetText(#URL)
;Get Filename
TrimURL.s = GetURLPart(URL, #PB_URL_Path)
Position = CountString(TrimURL, "/") + 1
File.s = StringField(TrimURL, Position, "/")
;Request Path
Folder.s = PathRequester("Where do you want to save '"+File+"'?", "C:\")
If Folder
*Parameters.DownloadData = AllocateMemory(SizeOf(DownloadData))
*Parameters\File = File
*Parameters\Folder = Folder
*Parameters\URL = URL
Thread = CreateThread(@DownloadWithProgress(), *Parameters)
SetGadgetText(#Start, "Cancel")
EndIf
EndIf
EndSelect
Case #PB_Event_CloseWindow
End
EndSelect
ForEver
EndIf