https://en.wikipedia.org/wiki/Segmented_file_transferSegmented file-transfer (also known as multisource file-transfer or swarming file-transfer) is a software method that intended to improve file download speed. It works by simultaneously downloading different portions of the computer file sourced from either multiple servers or a from a single server, recombining the parts into the single file requested. The majority of Download Manager applications work in this way.
Code: Select all
EnableExplicit
IncludeFile "WINHTTP_API.PBI"
Procedure.s WinHttpQueryHeadersEx(hRequest,QueryOpt.l,*QUERY_Buff,BufferSize.l = 1024)
If WinHttpQueryHeaders(hRequest,QueryOpt,"",*QUERY_Buff,@BufferSize,#WINHTTP_NO_HEADER_INDEX)
Protected String.s = PeekS(*QUERY_Buff,BufferSize)
EndIf
ProcedureReturn String
EndProcedure
Procedure.i WinHttpSendRequestEx(hConnect.i, HttpVerb.s, ObjectName.s, Scheme.l, Additionalheaders.s)
Protected iFlagScheme =#WINHTTP_FLAG_REFRESH:If Scheme = #INTERNET_SCHEME_HTTPS_WINHTTP:iFlagScheme | #WINHTTP_FLAG_SECURE:EndIf
Protected hRequest=WinHttpOpenRequest(hConnect,HttpVerb,ObjectName,"HTTP/1.1",
#WINHTTP_NO_REFERER,#WINHTTP_DEFAULT_ACCEPT_TYPES,iFlagScheme)
If hRequest
WinHttpSendRequest(hRequest,Additionalheaders,-1,#WINHTTP_NO_REQUEST_DATA,0,0,0)
WinHttpReceiveResponse(hRequest,0)
EndIf
ProcedureReturn hRequest
EndProcedure
Procedure.l WinHttpReadDataEx(hRequest,*DownloadMemory,MemorySize.l)
If MemorySize < 1:ProcedureReturn 0:EndIf
Protected ReciveSize.l
If WinHttpQueryDataAvailable(hRequest,@ReciveSize) =0
If GetLastError_():ReciveSize = -1:EndIf
Else
ReciveSize=0
If 0= WinHttpReadData(hRequest,*DownloadMemory,MemorySize,@ReciveSize):ReciveSize = -1:EndIf
EndIf
ProcedureReturn ReciveSize
EndProcedure
Structure sMultiDownloadSegment
hRequest.i
Range1.q
Range2.q
DownloadSize.q
CurrentMemoryPos.q
*DownloadMemory
EndStructure
Macro Check(Ver,Error)
If Ver = 0:ErrorPos = Error:Goto Clean:EndIf
EndMacro
#DEFAULT_USERAGENT = "Mozilla/5.0 (WinHTTP/5.1) like Gecko"
#DownloadMaxRate = 1024
#DownloadMaxSegment = 4
Procedure.q MultiDownloadSegment(DownloadLink.s, ; Http File Link
SaveName.s, ; File to wrtie the download data to
UserAgent.s = #DEFAULT_USERAGENT , ; Set User Agent
ProxyList.s = "", ; Use Proxy eg : "http(s)://IP:PORT"
ProxyLogin.s = "", ; Set proxy login
ProxyPassword.s = "") ; Set proxy password
Protected ErrorPos.q = 0
Protected uc.URL_COMPONENTS\dwStructSize=SizeOf(URL_COMPONENTS)
uc\dwHostNameLength = -1:uc\dwUrlPathLength = -1:uc\dwExtraInfoLength = -1
Check(WinHttpCrackUrl(DownloadLink,Len(DownloadLink),0,uc),-1)
Protected HostName.s = PeekS(uc\lpszHostName,uc\dwHostNameLength)
Protected File.s = PeekS(uc\lpszUrlPath,uc\dwUrlPathLength)
Protected Parameters.s = PeekS(uc\lpszExtraInfo,uc\dwExtraInfoLength)
Protected hSession = WinHttpOpen(UserAgent, #WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
#WINHTTP_NO_PROXY_NAME,#WINHTTP_NO_PROXY_BYPASS, 0)
Check(hSession,-2)
If ProxyList <> "" ;Set Proxy Setting
Protected proxy.WINHTTP_PROXY_INFO\dwAccessType = #WINHTTP_ACCESS_TYPE_NAMED_PROXY
proxy\lpszProxy = @ProxyList
Check(WinHttpSetOption(hSession, #WINHTTP_OPTION_PROXY, @proxy, SizeOf(WINHTTP_PROXY_INFO)),-5)
Check(WinHttpSetOption(hSession, #WINHTTP_OPTION_PROXY_USERNAME, @ProxyLogin, Len(ProxyLogin)),-5)
Check(WinHttpSetOption(hSession, #WINHTTP_OPTION_PROXY_PASSWORD, @ProxyPassword, Len(ProxyPassword)),-5)
EndIf
Protected hConnect = WinHttpConnect(hSession,HostName,uc\nPort,0)
Check(hConnect,-3)
Protected hRequest= WinHttpSendRequestEx(hConnect, "HEAD", File+Parameters, uc\nScheme, ;Get File Header Info
#WINHTTP_NO_ADDITIONAL_HEADERS)
Check(hRequest,-4)
Protected *QUERY_Buff = AllocateMemory(1024)
Protected iQuery.s = WinHttpQueryHeadersEx(hRequest,#WINHTTP_QUERY_STATUS_CODE,*QUERY_Buff) ;get Request Status code
Check(Bool(iQuery = "200"),-6)
Protected FileSize.q = Val(WinHttpQueryHeadersEx(hRequest,#WINHTTP_QUERY_CONTENT_LENGTH,*QUERY_Buff));Get file size
Check(FileSize,-7)
ErrorPos = FileSize
Debug "File Size : " + FileSize
Debug "Mime type : " + WinHttpQueryHeadersEx(hRequest,#WINHTTP_QUERY_CONTENT_TYPE,*QUERY_Buff)
Debug "DISPOSITION : " + WinHttpQueryHeadersEx(hRequest,#WINHTTP_QUERY_CONTENT_DISPOSITION,*QUERY_Buff) ; *File Name
Protected DownloadMaxPart.l = #DownloadMaxSegment
Protected p,RangeCal.q = 0
Dim aMultiDownloadSegment.sMultiDownloadSegment(4)
Protected *DownloadMemory = AllocateMemory(FileSize)
For p = 1 To DownloadMaxPart
With aMultiDownloadSegment(p)
\DownloadSize = FileSize / DownloadMaxPart
If p = DownloadMaxPart:\DownloadSize + Mod(FileSize , DownloadMaxPart):EndIf; if last chunk set end to last byte
\DownloadMemory = *DownloadMemory + RangeCal
\Range1 = RangeCal
RangeCal + \DownloadSize
\Range2 = RangeCal-1
\hRequest = WinHttpSendRequestEx(hConnect, "GET", File+Parameters, uc\nScheme,
"Range: bytes=" + Str(\Range1) + "-" + Str(\Range2)) ;Request Chunk
Debug WinHttpQueryHeadersEx(\hRequest,#WINHTTP_QUERY_STATUS_CODE,*QUERY_Buff) ;206 Partial Content (RFC 7233)
Check(\hRequest,-7)
EndWith
Next
Protected DownSize.l,AllDownSize.q,DownloadRate.q
Repeat
For p = 1 To DownloadMaxPart
With aMultiDownloadSegment(p)
If \CurrentMemoryPos < \DownloadSize
DownloadRate = \DownloadSize - \CurrentMemoryPos
If DownloadRate > #DownloadMaxRate:DownloadRate = #DownloadMaxRate:EndIf
DownSize = WinHttpReadDataEx(\hRequest, \DownloadMemory + \CurrentMemoryPos, DownloadRate);receiving data
EndIf
If DownSize > 0
\CurrentMemoryPos + DownSize
AllDownSize + DownSize
ElseIf DownSize = -1 ; download error
Check(0,-8)
EndIf
Next
EndWith
Until AllDownSize = FileSize
Debug AllDownSize
; ShowMemoryViewer(*DownloadMemory,FileSize)
CreateFile(0,SaveName)
WriteData(0,*DownloadMemory,FileSize)
CloseFile(0)
Clean:
If *QUERY_Buff:FreeMemory(*QUERY_Buff):EndIf
If *DownloadMemory:FreeMemory(*DownloadMemory):EndIf
For p = 1 To DownloadMaxPart
With aMultiDownloadSegment(p)
If \hRequest:WinHttpCloseHandle(\hRequest):EndIf
EndWith
Next
If hRequest:WinHttpCloseHandle(hRequest):EndIf
If hConnect:WinHttpCloseHandle(hConnect):EndIf
If hSession:WinHttpCloseHandle(hSession):EndIf
ProcedureReturn ErrorPos
EndProcedure
Debug MultiDownloadSegment("http://www.esa.int/var/esa/storage/images/esa_multimedia/images/2018/02/terrestrial_planet_magnetospheres/17366155-1-eng-GB/Terrestrial_planet_magnetospheres.jpg","Terrestrial_planet_magnetospheres.jpg")