Super simple download with progressbar

Post your working scripts, libraries and tools for AHK v1.1 and older
Bruttosozialprodukt
Posts: 463
Joined: 24 Jan 2014, 22:28

Super simple download with progressbar

24 Jan 2014, 22:39

I couldn't find a short script that shows a progressbar while downloading. There was always a big lib or function necessary. So I came up with this great piece of code:
v1.1

Code: Select all

DownloadFile(UrlToFile, SaveFileAs, Overwrite := True, UseProgressBar := True) {
    ;Check if the file already exists and if we must not overwrite it
      If (!Overwrite && FileExist(SaveFileAs))
          Return
    ;Check if the user wants a progressbar
      If (UseProgressBar) {
          ;Initialize the WinHttpRequest Object
            WebRequest := ComObjCreate("WinHttp.WinHttpRequest.5.1")
          ;Download the headers
            WebRequest.Open("HEAD", UrlToFile)
            WebRequest.Send()
          ;Store the header which holds the file size in a variable:
            FinalSize := WebRequest.GetResponseHeader("Content-Length")
          ;Create the progressbar and the timer
            Progress, H80, , Downloading..., %UrlToFile%
            SetTimer, __UpdateProgressBar, 100
      }
    ;Download the file
      UrlDownloadToFile, %UrlToFile%, %SaveFileAs%
    ;Remove the timer and the progressbar because the download has finished
      If (UseProgressBar) {
          Progress, Off
          SetTimer, __UpdateProgressBar, Off
      }
    Return
    
    ;The label that updates the progressbar
      __UpdateProgressBar:
          ;Get the current filesize and tick
            CurrentSize := FileOpen(SaveFileAs, "r").Length ;FileGetSize wouldn't return reliable results
            CurrentSizeTick := A_TickCount
          ;Calculate the downloadspeed
            Speed := Round((CurrentSize/1024-LastSize/1024)/((CurrentSizeTick-LastSizeTick)/1000)) . " Kb/s"
          ;Save the current filesize and tick for the next time
            LastSizeTick := CurrentSizeTick
            LastSize := FileOpen(SaveFileAs, "r").Length
          ;Calculate percent done
            PercentDone := Round(CurrentSize/FinalSize*100)
          ;Update the ProgressBar
            Progress, %PercentDone%, %PercentDone%`% Done, Downloading...  (%Speed%), Downloading %SaveFileAs% (%PercentDone%`%)
      Return
}
Examples of usage:
Spoiler
Screenshot:
Spoiler
Older versions:
Spoiler
Changelog:
Spoiler
I hope anyone of you finds this usefull. Tell me if you have ideas for improvement. :)
I posted the same thread on autohotkey.com.

edit:
Check out this post too. An even shorter example!
Last edited by Bruttosozialprodukt on 25 Jan 2014, 02:24, edited 1 time in total.
timeFlies
Posts: 146
Joined: 22 Oct 2013, 20:54
Location: Somewhere in the northern hemisphere.

Re: Super simple download with progressbar

25 Jan 2014, 01:23

Sweet! I love it!

One question: For example 2, where the heck does the file save?
Bruttosozialprodukt
Posts: 463
Joined: 24 Jan 2014, 22:28

Re: Super simple download with progressbar

25 Jan 2014, 02:21

In the scripts directory. Sorry I should have mentioned that. I will edit the examples a bit. :)
User avatar
joedf
Posts: 8958
Joined: 29 Sep 2013, 17:08
Location: Canada
Contact:

Re: Super simple download with progressbar

25 Jan 2014, 14:56

shorten the url? ;)

Code: Select all

MsgBox % ShortURL("https://www.google.com/search?q=AutoHotkey_FileDownload.zip")

ShortURL(p,l=50) {
	VarSetCapacity(_p, (A_IsUnicode?2:1)*StrLen(p) )
	DllCall("shlwapi\PathCompactPathEx"
		,"str", _p
		,"str", p
		,"uint", abs(l)
		,"uint", 0)
	return _p
}
Image Image Image Image Image
Windows 10 x64 Professional, Intel i5-8500, NVIDIA GTX 1060 6GB, 2x16GB Kingston FURY Beast - DDR4 3200 MHz | [About Me] | [About the AHK Foundation] | [Courses on AutoHotkey]
[ASPDM - StdLib Distribution] | [Qonsole - Quake-like console emulator] | [LibCon - Autohotkey Console Library]
Guest10
Posts: 578
Joined: 01 Oct 2013, 02:50

Re: Super simple download with progressbar

25 Jan 2014, 20:50

is the result supposed to be https://w.../search?q=AutoHotkey_FileDownload.zip? :geek:
joedf wrote:shorten the url? ;)

Code: Select all

MsgBox % ShortURL("https://www.google.com/search?q=AutoHotkey_FileDownload.zip")

ShortURL(p,l=50) {
	VarSetCapacity(_p, (A_IsUnicode?2:1)*StrLen(p) )
	DllCall("shlwapi\PathCompactPathEx"
		,"str", _p
		,"str", p
		,"uint", abs(l)
		,"uint", 0)
	return _p
}
User avatar
joedf
Posts: 8958
Joined: 29 Sep 2013, 17:08
Location: Canada
Contact:

Re: Super simple download with progressbar

25 Jan 2014, 21:53

euhhh... yes :)
Image Image Image Image Image
Windows 10 x64 Professional, Intel i5-8500, NVIDIA GTX 1060 6GB, 2x16GB Kingston FURY Beast - DDR4 3200 MHz | [About Me] | [About the AHK Foundation] | [Courses on AutoHotkey]
[ASPDM - StdLib Distribution] | [Qonsole - Quake-like console emulator] | [LibCon - Autohotkey Console Library]
tmplinshi
Posts: 1604
Joined: 01 Oct 2013, 14:57

Re: Super simple download with progressbar

25 Jan 2014, 22:56

Nice!

I've modified it a bit:
  • SaveFileAs can be blank.
  • Added time remain.
  • FileOpen execute only once before SetTimer.
  • Update progressbar per second.

Code: Select all

DownloadFile(URL, SaveFileAs = "", Overwrite := True, UseProgressBar := True) {
	if !SaveFileAs {
		SplitPath, URL, SaveFileAs
		StringReplace, SaveFileAs, SaveFileAs, `%20, %A_Space%, All
	}

    ;Check if the file already exists and if we must not overwrite it
      If (!Overwrite && FileExist(SaveFileAs))
          Return
    ;Check if the user wants a progressbar
      If (UseProgressBar) {
          ;Initialize the WinHttpRequest Object
            WebRequest := ComObjCreate("WinHttp.WinHttpRequest.5.1")
          ;Download the headers
            WebRequest.Open("HEAD", URL)
            WebRequest.Send()
          ;Store the header which holds the file size in a variable:
            FinalSize := WebRequest.GetResponseHeader("Content-Length")
          ;Create the progressbar and the timer
            Progress, H80, , Downloading..., %URL%
            File := FileOpen(SaveFileAs, "rw")
            SetTimer, __UpdateProgressBar, 1000
      }
    ;Download the file
      UrlDownloadToFile, %URL%, %SaveFileAs%
    ;Remove the timer and the progressbar because the download has finished
      If (UseProgressBar) {
          Progress, Off
          SetTimer, __UpdateProgressBar, Off
          File.Close()
      }
    Return
    
    ;The label that updates the progressbar
      __UpdateProgressBar:
          ;Get the current filesize and tick
            CurrentSize := File.Length ;FileGetSize wouldn't return reliable results
            CurrentSizeTick := A_TickCount
          ;Calculate the downloadspeed
            Speed := Round((CurrentSize/1024-LastSize/1024)/((CurrentSizeTick-LastSizeTick)/1000), 1)
          ;Calculate time remain
            TimeRemain := Round( (FinalSize-CurrentSize) / (Speed*1024) )

            time = 19990101
            time += %TimeRemain%, seconds
            FormatTime, mmss, %time%, mm:ss
            TimeRemain := LTrim(TimeRemain//3600 ":" mmss, "0:")
          ;Save the current filesize and tick for the next time
            LastSizeTick := CurrentSizeTick
            LastSize := CurrentSize
          ;Calculate percent done
            PercentDone := Round(CurrentSize/FinalSize*100)
          ;Update the ProgressBar
            Progress, %PercentDone%, %PercentDone%`% Done [Time: %TimeRemain%], Downloading...  (%Speed% Kb/s), Downloading %SaveFileAs% (%PercentDone%`%)
      Return
}
garry
Posts: 3769
Joined: 22 Dec 2013, 12:50

Re: Super simple download with progressbar

26 Jan 2014, 16:46

script remembers me to UrlDownLoadToVar
http://www.autohotkey.com/board/topic/1 ... ntry629473

Code: Select all

Modified=20140127
;-- urldownloadtovarx show randomjoke text -------------
F:="http://www.randomfunnyjokes.com"
w:= ComObjCreate("WinHttp.WinHttpRequest.5.1")
A1:
    w.Open("GET",F)
    w.Send()
    c:= % w.ResponseText
gosub,removetext
msgbox,262212,RandomJoke,%new%`n===============================================`n`n`n`nYes=Continue`nNO=Break
ifmsgbox,no
   exitapp
else
  {
  c=
  new=
  goto,a1
  }
return

removetext:
a=<td bordercolor="#FFFFFF" height="1"><font face="Verdana" size="2">   ;- TextBegin From
b=</font>&nbsp;</td>                                                    ;- TextEnd   Until
        StringGetPos,P1,c,%a%
        P1:=P1+68
        StringGetPos,P2,c,%b%
        P2:=P2+1
        PA:=(P2-P1)
        StringMid,New,c,P1,PA
stringreplace,New,New,<br>,,all
return
Last edited by garry on 27 Jan 2014, 07:54, edited 3 times in total.
Guest10
Posts: 578
Joined: 01 Oct 2013, 02:50

Re: Super simple download with progressbar

26 Jan 2014, 16:51

could you put this function in the main/core script? :ugeek:
garry wrote:script remembers me to UrlDownLoadToVar

Code: Select all

modified=20140126
;-- urldownloadtovar show randomjoke text -------------
f1=http://www.randomfunnyjokes.com
oHttp := ComObjCreate("WinHttp.Winhttprequest.5.1")
oHttp.open("GET",F1)
oHttp.send()
ac:= % oHttp.responseText
;- msgbox,%ac%                                                          ;- fulltext
a=<td bordercolor="#FFFFFF" height="1"><font face="Verdana" size="2">   ;- TextBegin From
b=</font>&nbsp;</td>                                                    ;- TextEnd   Until
        StringGetPos,P1,ac,%a%
        P1:=P1+68
        StringGetPos,P2,ac,%b%
        P2:=P2+1
        PA:=(P2-P1)
        StringMid,TextNew,ac,P1,PA
stringreplace,TextNew,TextNew,<br>,,all
msgbox,%TextNew%
return
garry
Posts: 3769
Joined: 22 Dec 2013, 12:50

Re: Super simple download with progressbar

26 Jan 2014, 17:08

urldownloadtovar found it last time here , but maybe also in other threads ( if disturbs can be removed )
http://www.autohotkey.com/board/topic/1 ... ntry629473
Guest10
Posts: 578
Joined: 01 Oct 2013, 02:50

Re: Super simple download with progressbar

26 Jan 2014, 17:52

sorry, i was not clear. I am glad you posted this script. what i meant was if you could "integrate" this script into the main/core original script (or the modified version by tmplinshi ) so that it becomes part of the main/core script (either the original or the one modified by tmplinshi)?
garry wrote:urldownloadtovar found it last time here , but maybe also in other threads ( if disturbs can be removed )
http://www.autohotkey.com/board/topic/1 ... ntry629473
garry
Posts: 3769
Joined: 22 Dec 2013, 12:50

Re: Super simple download with progressbar

26 Jan 2014, 18:26

this was just an example without progressbar and doesn't download to file ( downloads only short text to variable )
Bruttosozialprodukt
Posts: 463
Joined: 24 Jan 2014, 22:28

Re: Super simple download with progressbar

27 Jan 2014, 03:41

This would probably be a bit more complicated. I think, if you wanted to download something else than html-code/text to a variable, you would have to set the Content-Type header. And also I don't really know if there would be a reliable way to get the current file/variable size...

May I ask what kind of files you intend to download? I don't really see a reason to download a non-text file to a variable.
And for downloading html-code/text you usually don't need a progressbar at all because the files tend to be very small.
I for myself use this code to evaluate text/html-code:

Code: Select all

GetHtml(url) {
    WebRequest := ComObjCreate("WinHttp.WinHttpRequest.5.1")
    WebRequest.Open("GET", url)
    WebRequest.Send()
    Return, WebRequest.ResponseText
}
garry
Posts: 3769
Joined: 22 Dec 2013, 12:50

Re: Super simple download with progressbar

27 Jan 2014, 08:05

sorry for confusing , thank you for the example
UrlDownLoadToVar I use only for text , it doesn't need progressbar
( I was just remembering the command = ComObjCreate("WinHttp.WinHttpRequest.5.1") )
your script UrlDownLoadToFile with progressbar is very useful to download programs / files
and see what happens and how long it takes also with additional script from user "tmplinshi" .
jpginc
Posts: 124
Joined: 29 Sep 2013, 22:35

Re: Super simple download with progressbar

05 Feb 2014, 01:35

I've been using brutosozialprodukt's download to var function but had a couple of issues and also want to warn if the file is too large. Here is a modified function that I use now

Code: Select all

URLDownloadToVar(url, sizeWarn := false)
{   previousValue := ComObjError(false)
    WebRequest := ComObjCreate("WinHttp.WinHttpRequest.5.1")
    WebRequest.Open("HEAD", url)
    WebRequest.Send()
    requestStatus := WebRequest.status
    if(requestStatus < 200 || requestStatus > 299) ;2XX is success
    {   ComObjError(previousValue)
        return false
    } 
    size := WebRequest.GetResponseHeader("Content-Length") ;not all headers have a content length attribute!
    if(sizeWarn && size > sizeWarn)
    {   MsgBox, 4, JPGInc Warning, Warning the download you have requested is %size% bytes (ie large)`nDo you really want to download?
        IfMsgBox no
        {   ComObjError(previousValue)
            return false
        }
    }
    WebRequest.Open("GET", url)
    WebRequest.Send()
    response := WebRequest.ResponseText
    ComObjError(previousValue)
    Return response    
}
Last edited by jpginc on 14 Feb 2014, 03:37, edited 1 time in total.
Guest10
Posts: 578
Joined: 01 Oct 2013, 02:50

Re: Super simple download with progressbar

05 Feb 2014, 08:14

what happens if the file is too large? :geek:
jpginc wrote:I've been using brutosozialprodukt's download to var function but had a couple of issues and also want to warn if the file is too large. Here is a modified function that I use now

Code: Select all

URLDownloadToVar(url, sizeWarn := false)
{   previousValue := ComObjError(false)
    WebRequest := ComObjCreate("WinHttp.WinHttpRequest.5.1")
    WebRequest.Open("HEAD", url)
    WebRequest.Send()
    requestStatus := WebRequest.status
    if(requestStatus < 200 || requestStatus > 299) ;2XX is success
    {   ComObjError(previousValue)
        return false
    } 
    size := WebRequest.GetResponseHeader("Content-Length") ;not all headers have a content length attribute!
    if(sizeWarn && size > sizeWarn)
    {   MsgBox, 4, JPGInc Warning, Warning the download you have requested is %size% bytes (ie large)`nDo you really want to download?
        IfMsgBox no
        {   webrequest.Abort()
        }
    }
    WebRequest.Open("GET", url)
    WebRequest.Send()
    response := WebRequest.ResponseText
    ComObjError(previousValue)
    Return response    
}
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: Super simple download with progressbar

05 Feb 2014, 08:20

Use Bentschi's DownloadToString function

Code: Select all

DownloadToString(url, encoding="utf-8")
{
    static a := "AutoHotkey/" A_AhkVersion
    if (!DllCall("LoadLibrary", "str", "wininet") || !(h := DllCall("wininet\InternetOpen", "str", a, "uint", 1, "ptr", 0, "ptr", 0, "uint", 0, "ptr")))
        return 0
    c := s := 0, o := ""
    if (f := DllCall("wininet\InternetOpenUrl", "ptr", h, "str", url, "ptr", 0, "uint", 0, "uint", 0x80003000, "ptr", 0, "ptr"))
    {
        while (DllCall("wininet\InternetQueryDataAvailable", "ptr", f, "uint*", s, "uint", 0, "ptr", 0) && s>0)
        {
            VarSetCapacity(b, s, 0)
            DllCall("wininet\InternetReadFile", "ptr", f, "ptr", &b, "uint", s, "uint*", r)
            o .= StrGet(&b, r>>(encoding="utf-16"||encoding="cp1200"), encoding)
        }
        DllCall("wininet\InternetCloseHandle", "ptr", f)
    }
    DllCall("wininet\InternetCloseHandle", "ptr", h)
    return o
}
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
Bruttosozialprodukt
Posts: 463
Joined: 24 Jan 2014, 22:28

Re: Super simple download with progressbar

10 Feb 2014, 17:09

Here is an example that shows how you can download any file to the RAM:

Code: Select all

UrlToFile := "http://ahkscript.org/download/1.1/AutoHotkey111402_Install.exe"
SaveFileAs := A_ScriptDir . "\AHK_Install.exe"
Overwrite := True
If (FileExist(SaveFileAs)) {
    If (Overwrite)
        FileDelete, %SaveFileAs%
    Else
        Return
}
WinHttpObj := ComObjCreate("WinHttp.WinHttpRequest.5.1")
WinHttpObj.Open("GET", UrlToFile)
WinHttpObj.Send()
; If it is a text file like txt, html and json the text will be stored in WinHttpObj.ResponseText
; If it is a binary file like an exe for example you should check out: WinHttpObj.ResponseBody
If it's a binary file and you wanna store it on the HDD:

Code: Select all

ADODBObj := ComObjCreate("ADODB.Stream")
ADODBObj.Type := 1
ADODBObj.Open()
ADODBObj.Write(WinHttpObj.ResponseBody)
ADODBObj.SaveToFile(SaveFileAs, Overwrite ? 2:1)
ADODBObj.Close()
If it is a text file and you wanna store it on the HDD:

Code: Select all

FileAppend, % WinHttpObj.ResponseText, %SaveFileAs%
If you actually get problems with too large strings or variables in general, try to increase the size of the object variables before creating the objects:

Code: Select all

VarSetCapacity(WinHttpObj,10240000)
VarSetCapacity(ADODBObj,10240000)
In the end you might wanna kill the variables because they still contain the downloaded file if they were global:

Code: Select all

WinHttpObj := ""
VarSetCapacity(WinHttpObj,0)
ADODBObj := ""
VarSetCapacity(ADODBObj,0)
jpginc
Posts: 124
Joined: 29 Sep 2013, 22:35

Re: Super simple download with progressbar

14 Feb 2014, 03:45

@Guest10

If the size of the file is larger (in bytes) than the value you pass to the function it will pop up a message box asking you to confirm if you really want to download it. Maybe you were pointing out that my code had a bug and would download it anyway? I've added a return statement to the function in my original post.

@brutosozialprodukt

The issue i was having is that even if the url doesn't exist on the server it might return a ResponseText (ie the "this page doesn't exist" page). Checking to see if the .status variable is within the 200 range ensures that the url you are requesting actually exists
Dragonslayr
Posts: 17
Joined: 24 Feb 2014, 10:12

Re: Super simple download with progressbar

14 Apr 2014, 20:24

Very Nice!

Was wondering if you guys have any thoughts how one might compare the online version of a download, like ccleaner or whatever, to the version you have and ONLY download if newer..

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: No registered users and 169 guests