Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Super simple download with progress bar.


  • Please log in to reply
26 replies to this topic
Bruttosozialprodukt
  • Members
  • 457 posts
  • Last active: Oct 18 2015 08:47 AM
  • Joined: 20 Oct 2012
I couldn't find a short script that shows a progressbar while downloading. There was alreays a big lib or function necessary. So I came up with this great piece of code:
v1.1
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. :)

edit:
Check out this post:
http://www.autohotke...ar/#entry630902
an even shorter example!

Guest10
  • Members
  • 1216 posts
  • Last active: Oct 30 2015 05:12 PM
  • Joined: 27 Oct 2012

Nice script. Is there a way I can "Save As" in the above examples without Overwriting if files already exist on the disk?



RHCP
  • Members
  • 1228 posts
  • Last active: Apr 08 2017 06:17 PM
  • Joined: 29 May 2006

That's a really neat function!

 

if you place the label inside the function, then you don't have to use any global variables :)

I use a longer label name, as the label name is still global and so can obviously be called from anywhere else in the script i.e. clash with a users own label.

 
DownloadFile(UrlToFile, _SaveFileAs, Overwrite := True, UseProgressBar := True) {
    ;Check if the file already exists and if we must not overwrite it
      If (!Overwrite && FileExist(_SaveFileAs))
      {
        FileSelectFile, _SaveFileAs,S, %_SaveFileAs%
        if !_SaveFileAs ; user didnt select anything
          return
      }

    ;Check if the user wants a progressbar
      If (UseProgressBar) {
          ;Make variables global that we need later when creating a timer
            SaveFileAs := _SaveFileAs
          ;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")
            Progress, H80, , Downloading..., %UrlToFile% Download
            SetTimer, DownloadFileFunction_UpdateProgressBar, 100
      }
    ;Download the file
      UrlDownloadToFile, %UrlToFile%, %_SaveFileAs%
    ;Remove the timer and the progressbar  because the download has finished
      If (UseProgressBar) {
          Progress, Off
          SetTimer, DownloadFileFunction_UpdateProgressBar, Off
      }
      return

      DownloadFileFunction_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
}
 

Nice script. Is there a way I can "Save As" in the above examples without Overwriting if files already exist on the disk?

 
Try the above function with overwrite disabled.
DownloadFile("http://download-installer.cdn.mozilla.net/pub/firefox/releases/26.0/win32/en-US/Firefox%20Setup%2026.0.exe", A_ScriptDir "\firefox_setup.exe", 0)
 


Bruttosozialprodukt
  • Members
  • 457 posts
  • Last active: Oct 18 2015 08:47 AM
  • Joined: 20 Oct 2012

@Guest10 My second example does exactly what you want. The third parameter simply needs to be False or 0. ;)

@RHCP

Thanks, I wasn't aware that you could put a label into a function.

To make sure that a variable/function/label name is unique I usually just put 2 __ in the beginning.
FileSelectFile is something you should call before the function in my opinion.

I will update the first post.



garry
  • Spam Officer
  • 3219 posts
  • Last active: Sep 20 2018 02:47 PM
  • Joined: 19 Apr 2005

very nice Bruttosozialprodukt , found  another short  example  from user DataLife

;-------- http://www.autohotkey.com/board/topic/17915-urldownloadtofile-progress/page-4 ---
sUrl:="http://download-installer.cdn.mozilla.net/pub/firefox/releases/26.0/win32/en-US/Firefox%20Setup%2026.0.exe"
SplitPath, surl, name, dir, ext, name_no_ext, drive
sFile=%a_desktop%\%name%     ;- where to download
ifexist,%sFile%
   filedelete,%sFile%

;-----------------------------------------------
a:=a_tickcount
Progress, % "M W" . A_ScreenWidth//2, 0, 0 of 0
VarSetCapacity(vt, 4*11), nParam = 31132253353
Loop, Parse, nParam
	NumPut(RegisterCallback("DownloadProgress", "Fast", A_LoopField, A_Index-1), vt, 4*(A_Index-1))
DllCall("urlmon\URLDownloadToFileA", "Uint", 0, "str", sUrl, "str", sFile, "Uint", 0, "UintP", &vt)
delta:=((a_tickcount-a)/1000)
msgbox, 262208,Downloaded ,Downloaded in %delta% seconds

DownloadProgress(pthis, nProgress = 0, nProgressMax = 0, nStatusCode = 0, pStatusText = 0)
{
	If A_EventInfo = 6
	Progress, % p := 100 * nProgress//nProgressMax, %p%, % nProgress . " of " . nProgressMax
	Return 0
}
return
;----------------------------------



Bruttosozialprodukt
  • Members
  • 457 posts
  • Last active: Oct 18 2015 08:47 AM
  • Joined: 20 Oct 2012
Thanks this looks very interessting!
Some comments on what numput does here and what the dllcall parameters do would have been nice though. :)
Any idea where I can find documentation on urlmon\URLDownloadToFileA?

Godric
  • Members
  • 19 posts
  • Last active: Jun 02 2016 09:11 PM
  • Joined: 11 Nov 2013

Thank you so much for this script.



Guest10
  • Members
  • 1216 posts
  • Last active: Oct 30 2015 05:12 PM
  • Joined: 27 Oct 2012

could you evangelize this also on http://ahkscript.org/boards/ ?



Bruttosozialprodukt
  • Members
  • 457 posts
  • Last active: Oct 18 2015 08:47 AM
  • Joined: 20 Oct 2012
Here you go: http://ahkscript.org...&t=1674&p=10020

Bruttosozialprodukt
  • Members
  • 457 posts
  • Last active: Oct 18 2015 08:47 AM
  • Joined: 20 Oct 2012

Here is an alternative to UrlDownloadToFile:

UrlToFile := "http://ahkscript.org/download/1.1/AutoHotkey111402_Install.exe"
SaveFileAs := A_ScriptDir . "\AHK_Install.exe"
OverWrite := True

WinHttpObj := ComObjCreate("WinHttp.WinHttpRequest.5.1")
WinHttpObj.Open("GET", UrlToFile)
WinHttpObj.Send()

ADODBObj := ComObjCreate("ADODB.Stream")
ADODBObj.Type := 1
ADODBObj.Open()
ADODBObj.Write(WinHttpObj.ResponseBody)
ADODBObj.SaveToFile(SaveFileAs, Overwrite ? 2:1)
ADODBObj.Close()

For bigger files, using this this might be a bad idea, because the file will initially be downloaded into the RAM and only be moved to the disc, when the download finished.



capbat
  • Members
  • 191 posts
  • Last active: Feb 08 2017 06:57 PM
  • Joined: 29 Nov 2007

Glad to see that this thread is still alive.

Thank your for this script, I was looking for exactly this.

 

Bat



capbat
  • Members
  • 191 posts
  • Last active: Feb 08 2017 06:57 PM
  • Joined: 29 Nov 2007

Hi Brutto.

 

I have been using your app for a week or so without any problem but today I am having an error at line.

 FinalSize := WebRequest.GetResponseHeader("Content-Length")

The file on the server exist it has a size of 865,792 bytes.

The Error I am Getting is "The  requested Header was not found"

 

Any suggestion.

 

Bat



capbat
  • Members
  • 191 posts
  • Last active: Feb 08 2017 06:57 PM
  • Joined: 29 Nov 2007

I have fixed my problem above.

But I am wondering now if this could be adapted to a File copy or move FileDirCopy?.

 

Thanks.



jhabers
  • Members
  • 3 posts
  • Last active: Mar 19 2015 02:52 PM
  • Joined: 10 Mar 2015

Here is an alternative to UrlDownloadToFile:

UrlToFile := "http://ahkscript.org/download/1.1/AutoHotkey111402_Install.exe"
SaveFileAs := A_ScriptDir . "\AHK_Install.exe"
OverWrite := True

WinHttpObj := ComObjCreate("WinHttp.WinHttpRequest.5.1")
WinHttpObj.Open("GET", UrlToFile)
WinHttpObj.Send()

ADODBObj := ComObjCreate("ADODB.Stream")
ADODBObj.Type := 1
ADODBObj.Open()
ADODBObj.Write(WinHttpObj.ResponseBody)
ADODBObj.SaveToFile(SaveFileAs, Overwrite ? 2:1)
ADODBObj.Close()

For bigger files, using this this might be a bad idea, because the file will initially be downloaded into the RAM and only be moved to the disc, when the download finished.

 

 

 

 

 

I am trying to get this download method working with a status bar but cant seem to get it to work. The reson i like this download method is because I am running this from a USB thumbdrive and the other way goes very slow. Here is what I have. can anyone help?

	Url            =  http://download.adlice.com/RogueKiller/RogueKiller.exe
	DownloadAs     = RogueKiller.exe
	Overwrite      := True
	UseProgressBar := True
	DownloadFile(Url, DownloadAs, Overwrite, UseProgressBar)
	

;=================== Start Functions =====================================================================

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, 1000
      }
    ;Download the file 
	WinHttpObj := ComObjCreate("WinHttp.WinHttpRequest.5.1")
	WinHttpObj.Open("GET", UrlToFile)
	WinHttpObj.Send()

	ADODBObj := ComObjCreate("ADODB.Stream")
	ADODBObj.Type := 1
	ADODBObj.Open()
	ADODBObj.Write(WinHttpObj.ResponseBody)
	ADODBObj.SaveToFile(SaveFileAs, Overwrite ? 2:1)
	ADODBObj.Close()
	  
	  
    ;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
}


jhabers
  • Members
  • 3 posts
  • Last active: Mar 19 2015 02:52 PM
  • Joined: 10 Mar 2015

Anybody have any idea? Thanks!