[HV2] dl() - WinHttp 下载

许多实用脚本和封装函数, 可以让您编写脚本更加便捷高效

Moderators: tmplinshi, arcticir

arcticir
Posts: 694
Joined: 17 Nov 2013, 11:32

[HV2] dl() - WinHttp 下载

28 Dec 2015, 09:06

借鉴论坛代码

Code: Select all

f:=[]
f.url:="http://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/latest-mozilla-central-l10n/firefox-46.0a1.zh-CN.win64.zip"
f.bin:=1
f.Func:="test"
f.title:="firefox Download Test"
MsgBox % ObjTree(dl(f))


test(f){
	if f.name="Data"
	{
	for i,n in f
	s.= i "`t`t" n "`n"
	ToolTip,% s
	}
	else
	ToolTip	
}

Code: Select all

dl(url,byref data:="",byref charset:=""){
	static noerr 	:= ComObjError(false),https
		,header	:= {"user-agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.80 Safari/537.36"}
	this:=IsObject(url) ? url : {url:url, proxy:data, charset:charset}
	, this.WinHttp:=http:=this.WinHttp ? this.WinHttp : this.reuse ? https : https:=ComObjCreate("WinHttp.WinHttpRequest.5.1")
	, this.proxy 	? http.setproxy(2, this.proxy) : ""
	A_Record(this.url)
	if this.Func and ((type(this.Func)="BoundFunc") or this.Func:=Func(this.Func).Bind())
	{
		http.Open("HEAD",this.url),http.Send(this.post),this.CallBack:=[]
		WinHttp_Resolve_Header(this.Event_AllHeaders:=http.getAllResponseHeaders(),this.Event_Header:=[])
		,this.Len:=this.Event_Header["Content-Length"]
		,((i:= Round(this.Len/1024)) < 1024) ?(this.Promptl_Units:=1024,this.Promptl_Len:= "/" i " K") : (this.Promptl_Units:=1048576,this.Promptl_Len:= "/" Round(i/1024, 1) " M")

		,this.SetCapacity("pUnk",A_PtrSize*8),Addres:=&this
		,NumPut(this.GetAddress("pUnk")+A_PtrSize,pUnk:=this.GetAddress("pUnk"))

		for i,n in ["query","addref","release","OnResponseStart","OnResponseDataAvailable","OnResponseFinished",this.OnError?this.OnError:"OnError"]
			NumPut(this.CallBack[A_Index]:=RegisterCallback("WinHttp_Event_" n,"F",,Addres),pUnk+A_PtrSize*A_Index)

		pCPC:=ComObjQuery(http,"{B196B284-BAB4-101A-B69C-00AA00341D07}"),VarSetCapacity(GUID,16,0)
		,DllCall(NumGet(NumGet(pCPC+0,"ptr")+4*A_PtrSize,"ptr"),"ptr",pCPC,"ptr"
		,DllCall("ole32\CLSIDFromString","wstr","{f97f4e15-b787-4212-80d1-d380cbbf982e}","ptr",&GUID)>= 0?&GUID:"","ptr*",pCP)
		,DllCall(NumGet(NumGet(pCP+0,"ptr")+5*A_PtrSize,"ptr"),"ptr",pCP,"ptr",this.GetAddress("pUnk"),"uint*",Cookie)	
	}

	http.open(this.headers or (charset=0)?"head":this.post?"post" : "get",this.url,true)
	(this.page ?http.Option(2):=this.page : "")
	http.option(6) := this.NoRedirect ? 0 : 1

	if IsObject(this.header)
		for i,n in header
			this.header[i]?"":this.header[i]:=n
	else
		this.header:=header

	for i,n in this.header
		http.SetRequestHeader(i,n)

	((this.post) and !this.header["Content-Type"]
			? HTTP.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded"):"")

	,this.Timeout ? http.SetTimeouts(0, 60000, 30000, this.Timeout * 1000) : ""
	,Timeout:=this.Timeout = "" ? -1 : this.Timeout

	loop (this.try?this.try:1)
	{
		http.send(this.post)
		if (this.RetCode:=http.WaitForResponse(Timeout))=-1
			Break
		else if A_Index>=this.try
			return
	}
	this.Status:=http.Status,this.StatusText:=http.StatusText

	WinHttp_Resolve_Header(this.AllHeaders:=http.getAllResponseHeaders(),this)
	if this.headers or (charset=0)
		return this

	body := http.ResponseBody(), VarSetCapacity(data, size:= body.Length() + 1)
	,DllCall("oleaut32\SafeArrayAccessData", "ptr", ComObjValue(body), "ptr*",pdata)
	,RtlMoveMemory(&data, pdata, size)
	,DllCall("oleaut32\SafeArrayUnaccessData", "ptr", ComObjValue(body))
	,InStr(this["Content-Encoding"],"gzip") ? Size:=WinHttp_Gzip_Decomp(data, Size) : ""
	,this.Size:=Size

	return (this.file
		? (FileExist(dir:=SubStr(this.File,1,InStr(this.File,"\","",-1)))?"":DirCreate(dir)
			,FileOpen(this.file, "w").RawWrite(&data, size),this)
		: this.bin
			?(isByRef("data")?"":(this.Delete("Bin"),this.SetCapacity("Bin",Size),RtlMoveMemory(this.GetAddress("Bin"),&data,Size)),this)

			: ((encoding:=this.charset?this.charset:"UTF-8")
				, s:=StrGet(&data, size>>(encoding="utf-16"||encoding="cp1200"),encoding)
				, this.result ? (this.text:=s,this) : s))

}


WinHttp_Event_query(self,riid,pObj){
	return NumPut(self,pObj+0)*0
}

WinHttp_Event_addref(self){
	return 1
}

WinHttp_Event_release(self){
	return 0
}

WinHttp_Event_OnResponseStart(self,Status,ContentType){
	static code:={200:"OK",404:"Not Found"}
	this:=Object(A_EventInfo)
	,DllCall("QueryPerformanceFrequency","Int64*",Frequency)
	,DllCall("QueryPerformanceCounter","Int64*",Counter)
	,this.ResponseStart	:= code[status]?code[status]:Status
	,this.Current_Len	:= 0
	,this.Event_Frequency	:= Frequency
	,this.Event_Counter	:= Counter
}

WinHttp_Event_OnResponseDataAvailable(self,Data){
	this:=Object(A_EventInfo)
	SafeArrayGetUBound(NumGet(Data,"PTR"),1,getvar(sz:=0))
	this.Current_Len+=sz + 1
	DllCall("QueryPerformanceCounter", "Int64*", Counter)
	time:=(Counter-this.Event_Counter)/this.Event_Frequency
	if  (time>=1)
	{
		this.Event_Counter:=Counter
		if  this.Func
			this.Func.call({this:this,name:"Data",total:this.Len,Current:this.Current_Len,process:Round(this.Current_Len/this.Promptl_Units,1) this.Promptl_Len
				,scale:Round(this.Current_Len/this.Len*100,1),speed:Round((((this.Current_Len-this.Current_Mark)/1024)/time)),title:this.title})
		this.Current_Mark:=this.Current_Len
	}
}

WinHttp_Event_OnResponseFinished(self){
	this:=Object(A_EventInfo)
	for k,v in this.Delete("CallBack")
		GlobalFree(v)
	if  this.Func
		this.Func.call({this:this,name:"Finished",self:self})
}

WinHttp_Event_OnError(self,ErrorNumber,ErrorDescription){
	this:=Object(A_EventInfo)
	if  this.Func
		this.Func.call({this:this,name:"Error",self:self,ErrorNumber:ErrorNumber,ErrorDescription:ErrorDescription})
}

WinHttp_Resolve_Header(ByRef Header,ByRef this){
	Loop,parse,% Header,`n,`r `t
		(s:=InStr(A_LoopField,":"))
			? (this[p:=SubStr(A_LoopField, 1,s-1)]?(this[p].="||" Trim(SubStr(A_LoopField, s+1))):(this[p]:=Trim(SubStr(A_LoopField, s+1))))
			: this[A_LoopField]:=""
}

WinHttp_Gzip_Decomp(ByRef var, nSz:=0){
	static Module
	if !Module
		ifLoadLibrary(A_ahkDir "\Extend\Library\gzip.dll")
	vSz :=  NumGet( var,nsz-4 ), VarSetCapacity( out,vsz,0)
		,DllCall( "GZIP\InitDecompression" ),DllCall( "GZIP\CreateDecompression", UIntP,CTX, UInt,1 )
	If ( DllCall( "GZIP\Decompress", UInt,CTX, UInt,&var, UInt,nsz, UInt,&Out, UInt,vsz, UIntP,input_used, UIntP,output_used ) = 0 && ( Ok := ( output_used = vsz ) ) )
		VarSetCapacity( var,64 ), VarSetCapacity( var,0 ), VarSetCapacity( var,vsz,32 ), RtlMoveMemory(&var,&out,vsz )
	DllCall( "GZIP\DestroyDecompression", UInt,CTX ), DllCall( "GZIP\DeInitDecompression" )
	Return Ok ? vsz : 0
	
ifLoadLibrary(dll){
	Return (Module:=DllCall("GetModuleHandle", "Str",dll, "Ptr"))?Module:DllCall("LoadLibrary","Str",dll, "Ptr")
}
}

Return to “脚本函数”

Who is online

Users browsing this forum: No registered users and 42 guests