fures
Joined: 31 Jan 2008 Posts: 30
|
Posted: Mon Jul 14, 2008 2:29 pm Post subject: Concept: Multi Download in Background |
|
|
I've made this proof of concept to make a more controllable URLDownloadToFile variant.
- This script creates a download queue
- Launches downloads as separate processes
- Monitors status of downloads
All that runs in the background, so your script can run undisturbed.
Hope it will be useful.
| Code: |
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%
#Persistent
Dnl =
Max_Threads = 4
SetTimer,Check_myDnlList,1000
SetTimer,CheckReadyDNL,1000
Loop, 8
{
thisurl = http://news.google.com
FileSaveName = %A_ScriptDir%\Google.html
Dnl = %Dnl%¤%thisurl%|%FileSaveName% ;Download Queue
}
MsgBox, The downloads have been started, just wait.`n`nThe script could run forward...
Return
Check_myDnlList:
Critical
Loop, parse, Dnl, ¤
{
IfEqual,A_LoopField,
Continue
StringSplit,tDnl,A_LoopField,|
turl = %tDnl1%
tfil = %tDnl2%
delthis =
Loop, %Max_Threads% ;Check for empty runIDs
{
runIDx = runID%A_Index%
IniRead, runID, %A_ScriptDir%\myDownload.ini, Running, %runIDx%, %A_Space%
If !runID
{
;scriptname "url" "save file" "pos-index" "dupl-filter"
IfExist,C:\Program Files\AutoHotkey\AutoHotkey.exe
Run, "C:\Program Files\AutoHotkey\AutoHotkey.exe" "myDownload.ahk" "%turl%" "%tfil%" %A_Index%,,,runID
else IfExist,myDownload.exe
Run, "myDownload.exe" "%turl%" "%tfil%" %A_Index%,,,runID
else
{
MsgBox, The myDownload.exe component is missing, and AutoHotkey is not found.
ExitApp
}
IniWrite, %runID%|%turl%|%tfil%, %A_ScriptDir%\myDownload.ini, Running, %runIDx%
delthis = 1
Break
}
}
If delthis
{
;here a regexreplace would be better...
StringReplace, Dnl, Dnl, %A_LoopField%,, A
StringReplace, Dnl, Dnl, ¤¤,¤, A
}
}
Return
CheckReadyDNL:
Critical
Loop, %Max_Threads% ;Check for finished runID
{
runIDx = runID%A_Index%
IniRead, runID, %A_ScriptDir%\myDownload.ini, Running, %runIDx%, %A_Space%
If runID
{
StringSplit,tDnl,runID,|
trunID = %tDnl1%
turl = %tDnl2%
tfil = %tDnl3%
Process, Exist, %trunID%
If not ErrorLevel ;This is ready
{
IniWrite, %A_Space%, %A_ScriptDir%\myDownload.ini, Running, %runIDx%
}
}
}
Return
|
The download script (copy into the same folder)
| Code: |
#SingleInstance OFF
#NoTrayIcon
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
if 0 < 2 ; The left side of a non-expression if-statement is always the name of a variable.
{
;MsgBox This script requires at least 2 incoming parameters but it only received %0%.
; ExitApp
}
StringReplace, 1, 1, ",, All
StringReplace, 2, 2, ",, All
StringReplace, 3, 3, ",, All
;StringReplace, 4, 4, ",, All
url = %1%
save = %2%
pospar = %3%
if not url
{
url = http://www.bbdo.hu/mytest/magyar/works/007_work1.wmv
sleep, 5000
}
if not save
save = temp.wmv
if not pospar
pospar = 1
SplitPath,save,file
rfile := SubStr(file,InStr(file,"_")+1)
;StringSplit,rfile,file,_
urlfile := file
If rfile
urlfile := rfile
;message = 0x11100
;OnMessage(message, "SetCounter")
Loop, 20
{
pos%A_Index% := ((A_Index-1) * 31)+100
}
posy := pos%pospar%
;Progress, x10 y%posy% M2 T FM8 FS8 h80 w300, , ., mydnl
;wn := WinExist("mydnl")
;WinMinimize,ahk_id %wn%
Gui, +lastfound -caption +Border +ToolWindow ;+owner
wn := WinExist()
Gui, Add, Progress, Section x55 vProgressBar w100 +Smooth cBDDCEF
Gui, Font, bold
Gui, Add, Text, ys, %urlfile%
Gui, Add, Text, vProgressN BackgroundTrans x90 ys+2, connecting...
Gui, Font
Gui, Add, Text, vKB ys w150, getting info...
Gui, Add, Button, ys x5 w48 h20 gExit, Close
Gui, Show, NoActivate x10 y%posy% w300 h30, Downloading...
total := HttpQueryInfo(url, 5)
If not total
ExitApp
GuiControl, , KB, % "(" round(total/1024) " kB)"
FileDelete, %save%
res:=Download(url, save, message, 500)
ExitApp
Return
Exit:
GuiEscape:
GuiClose:
ExitApp
Download(url, save, msg = 0x1100, sleep = 1000) {
;total := HttpQueryInfo(url, 5)
Global total
SetTimer, _dlprocess, %sleep%
UrlDownloadToFile, %url%, %save%
SetTimer, _dlprocess, Off
Return, ErrorLevel
_dlprocess:
FileGetSize, current, %save%, K
;Process, Exist
;PostMessage, msg, current * 1024, total, , ahk_pid %ErrorLevel%
SetCounter(current * 1024, total)
Exit
}
; SetCounter(wParam, lParam) {
; global url,save
; SplitPath,url,urlfile
; progress := Round(wParam / lParam * 100)
; wParam := wParam // 1024
; lParam := lParam // 1024
; Progress, %progress%, %url%, %urlfile%: %wParam% kB of %lParam% kB, %progress%`% - Downloading...
; }
SetCounter(wParam, lParam) {
progress := Round(wParam / lParam * 100)
GuiControl, , ProgressBar, %progress%
GuiControl, , ProgressN, %progress%`%
;wParam := wParam // 1024
;lParam := lParam // 1024
;GuiControl, , KB, (%wParam% kB of %lParam% kB)
;Gui, Show, , %progress%`% - Downloading...
}
/* ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; HttpQueryInfo ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
QueryInfoFlag
HTTP_QUERY_RAW_HEADERS = 21
Receives all the headers returned by the server.
Each header is terminated by "\0". An additional "\0" terminates the list of headers.
HTTP_QUERY_CONTENT_LENGTH = 5
Retrieves the size of the resource, in bytes.
HTTP_QUERY_CONTENT_TYPE = 1
Receives the content type of the resource (such as text/html).
Find more at: http://msdn.microsoft.com/library/en-us/wininet/wininet/query_info_flags.asp
Proxy Settings:
INTERNET_OPEN_TYPE_PRECONFIG 0 // use registry configuration
INTERNET_OPEN_TYPE_DIRECT 1 // direct to net
INTERNET_OPEN_TYPE_PROXY 3 // via named proxy
INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY 4 // prevent using java/script/INS
*/ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
HttpQueryInfo(URL, QueryInfoFlag=21, Proxy="", ProxyBypass="") {
hModule := DllCall("LoadLibrary", "str", "wininet.dll")
If (Proxy != "")
AccessType=3
Else
AccessType=1
io_hInternet := DllCall("wininet\InternetOpenA"
, "str", "" ;lpszAgent
, "uint", AccessType
, "str", Proxy
, "str", ProxyBypass
, "uint", 0) ;dwFlags
If (ErrorLevel != 0 or io_hInternet = 0) {
DllCall("FreeLibrary", "uint", hModule)
return, -1
}
iou_hInternet := DllCall("wininet\InternetOpenUrlA"
, "uint", io_hInternet
, "str", url
, "str", "" ;lpszHeaders
, "uint", 0 ;dwHeadersLength
, "uint", 0x80000000 ;dwFlags: INTERNET_FLAG_RELOAD = 0x80000000 // retrieve the original item
, "uint", 0) ;dwContext
If (ErrorLevel != 0 or iou_hInternet = 0) {
DllCall("FreeLibrary", "uint", hModule)
return, -1
}
VarSetCapacity(buffer, 1024, 0)
VarSetCapacity(buffer_len, 4, 0)
Loop, 5
{
hqi := DllCall("wininet\HttpQueryInfoA"
, "uint", iou_hInternet
, "uint", QueryInfoFlag ;dwInfoLevel
, "uint", &buffer
, "uint", &buffer_len
, "uint", 0) ;lpdwIndex
If (hqi = 1) {
hqi=success
break
}
}
IfNotEqual, hqi, success, SetEnv, res, timeout
If (hqi = "success") {
p := &buffer
Loop
{
l := DllCall("lstrlen", "UInt", p)
VarSetCapacity(tmp_var, l+1, 0)
DllCall("lstrcpy", "Str", tmp_var, "UInt", p)
p += l + 1
res := res . "`n" . tmp_var
If (*p = 0)
Break
}
StringTrimLeft, res, res, 1
}
DllCall("wininet\InternetCloseHandle", "uint", iou_hInternet)
DllCall("wininet\InternetCloseHandle", "uint", io_hInternet)
DllCall("FreeLibrary", "uint", hModule)
return, res
}
|
PS: I used some code from other coders in my script:
- HTTPQueryInfo from olfen
Thanks.
Cheers,
fures |
|