1 (изменено: stealzy, 2016-01-01 23:36:08)

Тема: AHK:[function] URLDownloadToVar

Альтернатива команде URLDownloadToFile.
Обработка ошибок, таймауты, печеньки, прокси, referrer, user-agent...
В случае успеха возращает содержимое URL,
в случае ошибки возращает false и пишет причину ошибки в ErrorLevel.

Функция с примером:

Request:={}, i:=0
Request[++i] := ["http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"]
Request[++i] := ["http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js",, timeout:=0.3]  ; too little time
; Request[++i] := ["http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js",, timeout:=1.5]
Request[++i] := ["http://ajax.google-shmoogle.com"]  ; Non-exist domain
Request[++i] := ["http://ajax.googleapis.com/ho-ho!"]  ; Not found - 404
Request[++i] := ["http://www.tingchina.com/play/yousheng/flash.asp?id=24366&inum=1&flei=恐怖惊悚&bookname=我当阴曹官的那几年&filename=001.mp3&rand=16&nexturl=play_24366_1.htm"] ; not so easy to get this page
Request[++i] := ["http://www.tingchina.com/play/yousheng/flash.asp?id=24366&inum=1&flei=恐怖惊悚&bookname=我当阴曹官的那几年&filename=001.mp3&rand=16&nexturl=play_24366_1.htm", Referer:="http://www.tingchina.com/yousheng/24366/play_24366_0.htm"]
Request[++i] := ["http://www.tingchina.com/play/yousheng/flash.asp?id=24366&inum=1&flei=恐怖惊悚&bookname=我当阴曹官的那几年&filename=001.mp3&rand=16&nexturl=play_24366_1.htm", Referer:="http://www.tingchina.com/yousheng/24366/play_24366_0.htm",,,,,,,, Charset:="gb2312"]

Loop % i ;Request.MaxIndex()
	MsgBox,, % ((answer:=UrlDownloadToVar(Request[A_Index]*))=false  ?  "Error:"  :  "Success:") " " (URL:=Request[A_Index][1]), % answer=false ? ErrorLevel : answer
ExitApp
Esc::ExitApp
Return

UrlDownloadToVar(URL, Referer="", TimeoutSec=-1, UserAgent="", Cookie="", Proxy="", ProxyBypassList="", EnableRedirects="", URLCodePage="", Charset="") {
	; If something wrong - return false, put explanation in ErrorLevel
	; autors: stealzy, tuzi
	; More about WinHttpRequest: https://msdn.microsoft.com/en-us/library/windows/desktop/aa383979%28v=vs.85%29.aspx

	WebRequest := ComObjCreate("WinHttp.WinHttpRequest.5.1")
	t := URLCodePage ? WebRequest.Option(2):=URLCodePage :
	t := (EnableRedirects <> "") ? WebRequest.Option(6):=EnableRedirects :
	t := Proxy ? WebRequest.SetProxy(2,Proxy,ProxyBypassList) :
	; WebRequest.SetTimeouts(ResolveTimeout:=0, ConnectTimeout:=60000, SendTimeout:=30000, ReceiveTimeout:=30000) ; time in ms
	; https://msdn.microsoft.com/library/windows/desktop/aa384061%28v=vs.85%29.aspx
	try WebRequest.Open("GET", URL, true)
		catch	Error {
			ErrorLevel := "Wrong URL format"
			return false
		}

	t := Cookie ? WebRequest.SetRequestHeader("Cookie", Cookie) :
	t := Referer ? WebRequest.SetRequestHeader("Referer", Referer) :
	t := UserAgent ? WebRequest.SetRequestHeader("User-Agent", UserAgent) :
	WebRequest.Send()
	t := A_TickCount
	try Suc:=WebRequest.WaitForResponse(TimeoutSec+0) ; Timeout in seconds; without "+0" interpreted as string
		catch	Error {
			OutputDebug % "Error WaitForResponse: " A_TickCount - t
			ErrorLevel := "No internet access / No existing domain"
			return false
		}
	OutputDebug % "Success WaitForResponse: " A_TickCount - t 	; if no internet access, ≈ 21-23 sec
	try HTTPStatusCode := WebRequest.Status
		catch	Error {
			ErrorLevel := "WebRequest.Status not ready = timeout expired"
			return false
		}
	if (SubStr(HTTPStatusCode, 1, 1) ~= "4|5") { ; 4xx — Client Error, 5xx — Server Error. wikipedia.org/wiki/List_of_HTTP_status_codes
		ErrorLevel := "Error HTTP Status Code: " HTTPStatusCode
		return false
	}

	If (Charset="") {
		try ResponseText := WebRequest.ResponseText()
			catch	Error {
				ErrorLevel := " WebRequest.ResponseText not ready = timeout expired"
				return false
			}
	} Else {
		ADO := ComObjCreate("adodb.stream")  
		ADO.Type := 1 
		ADO.Mode := 3
		ADO.Open() 
		ADO.Write(WebRequest.ResponseBody())  
		ADO.Position := 0
		ADO.Type := 2 
		ADO.Charset := Charset    
		ResponseText := ADO.ReadText()   
	}
	return ResponseText
}

Если знаете наглядные примеры зависимости отдаваемого контента от юзер-агента или куков - присылайте, добавлю к примерам.
Если знаете, как загрузить только первые Х байт файла, вообще было бы отлично.

+ DD

2

Re: AHK:[function] URLDownloadToVar

Если знаете, как загрузить только первые Х байт файла, вообще было бы отлично.

http://forum.script-coding.com/viewtopi … 761#p83761

3 (изменено: stealzy, 2016-01-02 01:29:19)

Re: AHK:[function] URLDownloadToVar

Спасибо за наводку на тему. Код в сообщении однако нерабочий. Буду разбираться.
_______________
UPD:
Понял из-за чего ошибки.
Гитхаб не отдает заголовок Content-Length отдельно. Только все заголовки вместе. Заголовок Accept-Ranges не отдает вовсе (ну и не надо, поставим Exception).
Но это для zip. Если говорить про ссылку из сообщения ("http://ahkscript.org/download/ahk-install.exe"), то там даже Content-Length нету.

4

Re: AHK:[function] URLDownloadToVar

Рабочий, просто там идет переадресация инсталлятора на github.

5 (изменено: DD, 2018-02-03 07:58:57)

Re: AHK:[function] URLDownloadToVar

Как записать эту часть кода


MsgBox,, % ((answer:=UrlDownloadToVar(Request[A_Index]*))=false  ?  "Error:"  :  "Success:") " " (URL:=Request[A_Index][1]), % answer=false ? ErrorLevel : answer

в виде —


zzzzz = ((answer:=UrlDownloadToVar(Request[A_Index]*))=false  ?  "Error:"  :  "Success:") " " (URL:=Request[A_Index][1]), % answer=false ? ErrorLevel : answer
MsgBox, %zzzzz%

Чтобы в MsgBox была только переменная?

6

Re: AHK:[function] URLDownloadToVar

В переменную answer сохраняется результат выполнения функции UrlDownloadToVar.
Если вам не нужен разбор ответов от сервера, то можно сократить так:

Loop % i ;Request.MaxIndex()
	MsgBox % UrlDownloadToVar(Request[A_Index]*)
+ DD