Download files with an progress bar indicator

Hello,

hope this is useful for somebody. I’ve included my comments inside the code for future reference :wink:

Your comments are welcome!


(*
basic functions of this handler:
1. gets the actual size of the file to be downloaded
2. starts the download as a (parallel to the script) background process
3. repeated checks the size of the downloaded file until it matched the actual size
4. posts the information into the progress bar

Tested under Snow Leopard only, you need Bruce Phillips amazing BP Progress Bar 1.0, available here:
http://scriptbuilders.net/files/bpprogressbar1.0.html
Please install BP Progress Bar 1.0 in YourUserFolder/Library/Scripts/BP Progress/ or change the path inside the handler.
For use as an App it is recommended to include both "BP Progress"-files inside the "Contents/Resources" - directory of the App-Bundle. 
In this case define the directory definition as follows:
set ProgressBar to load script alias ((path to resource "BP Progress Bar Controller.scpt") as text)
set ProgressBarApp to POSIX path of ((path to resource "BP Progress Bar.app") as text)
*)

set mydownloadURL to "http://developer.apple.com/mac/library/documentation/applescript/conceptual/applescriptlangguide/AppleScriptLanguageGuide.pdf"
myFileDownload(mydownloadURL) --calls the handler
set pathtodownloadedFile to result --result back from the handler: path/filename as POSIX

--Handler for Download with Progress Bar starts here
on myFileDownload(downloadURL)
	
	set oldDelimiter to AppleScript's text item delimiters
	set AppleScript's text item delimiters to "/"
	set downloadfilename to text item -1 of downloadURL
	set downloadFolder to POSIX path of (path to temporary items)
	
	-- initialize BP Progress
	-- **** directory definition **** next 2 lines must be edited to point to wherever you actually put ProgressBar. ****
	set ProgressBar to load script alias (((path to scripts folder) as text) & "BP Progress:BP Progress Bar Controller.scpt")
	set ProgressBarApp to POSIX path of (((path to scripts folder) as text) & "BP Progress:BP Progress Bar.app")
	tell ProgressBar to initialize("File-Download") -- put name of script here (same as title bar of script)
	--Next command is only necessary if this script is saved as an App  and includes the BP Progress -files in the resources folder in the app package, so that it is portable. 
	--When the script is run for the first time on a new machine, it always asks where the application is. Next line starts it and Apple Script knows its location.
	do shell script "open " & quoted form of ProgressBarApp
	-- Start of Script to use ProgressBar Controller
	tell ProgressBar
		barberPole(true)
		setStatusTop to "Starting Download."
		setStatusBottom to "Please wait..."
	end tell
	
	--To get the actual size of the file on the server, use curl and pipe the output to grep
	--if the file isnt available the script stops, shows a dialog
	try
		do shell script "curl " & downloadURL & " -I | grep 'Content-Length:\\|content-length:'| grep -v grep"
		set returnResult to the result as text
		set thefilesize to the last word of returnResult as number
	on error
		tell ProgressBar to quit
		tell application "Finder"
			activate
			display dialog "File is not available. Please check the URL and your internet connection!" buttons {"Cancel"} cancel button "Cancel" default button "Cancel" giving up after 15
			quit
		end tell
	end try
	
	--it is important to start the download as a background process in order to run the loop for the progress bar 
	--if an old download exists it will be deleted first
	try
		do shell script "rm " & downloadFolder & downloadfilename
	end try
	do shell script "curl " & downloadURL & " -o " & downloadFolder & downloadfilename & " -m 9000 > /dev/null 2>&1 & echo $!"
	--it is not necessary to save the pid below but it is useful if you want to abort the download or use it otherwise
	set pid to the result
	--wait until the download is started and the file is created, after 30 sec this will be canceled
	repeat 30 times
		tell application "Finder" to if not (exists downloadFolder & downloadfilename as POSIX file) then
			delay 1
		else
			exit repeat
		end if
	end repeat
	tell application "Finder" to if not (exists downloadFolder & downloadfilename as POSIX file) then
		tell ProgressBar to quit
		display dialog "Download cannot be started. You need admin permissions on local directories!" buttons {"Cancel"} cancel button "Cancel" default button "Cancel" giving up after 15
		quit
	end if
	
	-- Stop the barber pole, set up for the progress bar
	tell ProgressBar
		barberPole(false)
		setMax to thefilesize -- to match the items to be processed below
		setStatusTop to "Download of " & downloadfilename
	end tell
	--the loop monitors the size of the downloaded file with a simple ls command
	--because the progress bar needs the differences of the downloadsize from one loop to next save it to a variable
	set downloadedSize to 0
	set lastdownloadedSize to 0
	repeat until downloadedSize is equal to thefilesize
		delay 1 --delay for the repeat, higher delays generates less proc load and less steps on the bar
		tell application "Finder"
			set AppleScript's text item delimiters to space
			do shell script "ls -la " & downloadFolder & " | grep " & downloadfilename
			set downloadedSize to text item -5 of the result as number
			set downloadDiffSize to downloadedSize - lastdownloadedSize
			set lastdownloadedSize to downloadedSize
		end tell
		--feed the downloadedSize and the actual file size into the progress bar and increase the bar with the difference
		tell ProgressBar
			setStatusTop to "Download of " & downloadfilename
			setStatusBottom to (downloadedSize & " of " & thefilesize & " Bytes") as text
			increase by downloadDiffSize
		end tell
	end repeat
	tell ProgressBar to quit
	set AppleScript's text item delimiters to oldDelimiter
	--rounds the output to MB with 2 digits after the dot
	set downloadedsizeMB to (round (downloadedSize / 1024 / 1024) / 0.01 rounding as taught in school) * 0.01
	display dialog "Download of " & downloadfilename & " is finished with size: " & downloadedsizeMB & " MB" buttons {"OK"} default button "OK" giving up after 15
	return downloadFolder & downloadfilename
end myFileDownload

Thanks
Nils