WinBatch Tech Support Home

Database Search

If you can't find the information using the categories below, post a question over in our WinBatch Tech Support Forum.

TechHome

Web UDFs

Can't find the information you are looking for here? Then leave a message over on our WinBatch Tech Support Forum.

Download File With Progress Display and Timeout

 Keywords:  Download File Progress Display Timeout WriteFile

I did this function for the webspider project, it's a general function that can be handy. It downloads a file from the internet, the advantages are that it shows the download progress and you can set a timeout if the server stops sending data (you can check it unplugging the connection), it's done with api calls.

The easiest way I could find to download the file without knowing its size was using the WriteFile api. http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/base/writefile.asp

;-----------------------------------------------------------------------------------------;
;DownloadFile : Downloads bytes from the Internet and saves them to a localfile.			   ;
;               Displays bytes copied and server file size.											;
;Guido 01/03																										;
;-----------------------------------------------------------------------------------------;
;host      : host name of an Internet server or the IP number of the site,					   ;
;            in ASCII dotted-decimal format.															   ;
;object    : name of the target object, generally a file name, an executable module, 	   ;
;            or a search specifier.  																	   ;
;username  : name of the user to log on.																   ;
;password  : password to use to log on.																	;
;referer   : URL of the document from which the URL in the request was obtained.			   ;
;localfile : the name of the file to create.															   ;
;timeout	  : seconds the function will wait while data is not being recieved.             ;
;-----------------------------------------------------------------------------------------;
;Returns   : If the function succeeds returns the HTTP Response Code.							;
;            If if fails returns:																			;
;            -1 local file could not be created														   ;
;            -2 timeout ocurred																			   ;
;            -3 internet error, http request could not be sent									   ;
;-----------------------------------------------------------------------------------------;
;Notes : Only for http downloads, default port, without proxy.                            ;
;        It does not cache the data being downloaded.											      ;
;        It will try to download only if it recieves a 200 (HTTP_STATUS_OK) response code.;
;		   If the local file already exists it will be overwritten.								   ;
;-----------------------------------------------------------------------------------------;
#definefunction DownloadFile(host,object,username,password,referer,localfile,timeout)
;dll handles
wininet=dllload(StrCat(DirWindows(1),"wininet.dll"))
kernel32=dllload(StrCat(DirWindows(1),"kernel32.dll"))

;init connection
tophandle=dllcall(wininet,long:"InternetOpenA",lpstr:"Microsoft Internet Explorer",long:1,lpnull,lpnull,long:0) ;INTERNET_OPEN_TYPE_DIRECT
connecthandle=dllcall(wininet,long:"InternetConnectA",long:tophandle,lpstr:host,long:80,lpstr:username,lpstr:password,long:3,long:0,long:0) ;INTERNET_DEFAULT_HTTP_PORT  INTERNET_SERVICE_HTTP
openreqhandle=dllcall(wininet,long:"HttpOpenRequestA",long:connecthandle,lpstr:"GET",lpstr:object,lpnull,lpstr:referer,lpnull,long:67108864,long:0) ;INTERNET_FLAG_NO_CACHE_WRITE

;set recieve timeout
toutbuf=binaryalloc(4)
binarypoke4(toutbuf,0,timeout*1000)
dllcall(wininet,long:"InternetSetOptionA",long:openreqhandle,long:6,lpbinary:toutbuf,long:4) ;INTERNET_OPTION_RECEIVE_TIMEOUT
binaryfree(toutbuf)

sendreq=dllcall(wininet,long:"HttpSendRequestA",long:openreqhandle,lpstr:"",long:0,lpstr:"",long:0)
;internet error
if sendreq==0 
  dllcall(wininet,long:"InternetCloseHandle",long:tophandle)
  dllfree(wininet)
  dllfree(kernel32)
  return -3
endif
  
;query status code
indexbuf=binaryalloc(4)
infobuf=binaryalloc(4)
infobufsize=binaryalloc(4)
binarypoke4(infobufsize,0,4)
dllcall(wininet,long:"HttpQueryInfoA",long:openreqhandle,long:19|536870912,lpbinary:infobuf,lpbinary:infobufsize,lpbinary:indexbuf) ;HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER
stcode=binarypeek4(infobuf,0)

;query size
binarypoke4(indexbuf,0,0)
binarypoke4(infobuf,0,0)
dllcall(wininet,long:"HttpQueryInfoA",long:openreqhandle,long:5|536870912,lpbinary:infobuf,lpbinary:infobufsize,lpbinary:indexbuf) ;HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER
size=binarypeek4(infobuf,0)
if size==0 then size="Unknown"
binaryfree(infobuf)
binaryfree(indexbuf)
binaryfree(infobufsize)
 
if stcode==200 ;OK
  
  ;create localfile
  hfile=dllcall(kernel32,long:"CreateFileA",lpstr:localfile,long:1073741824,long:0,lpnull,long:2,long:128,lpnull) ;GENERIC_WRITE  CREATE_ALWAYS  FILE_ATTRIBUTE_NORMAL
  ;file error
  if hfile==-1
    dllcall(wininet,long:"InternetCloseHandle",long:tophandle)
    dllfree(wininet)
    dllfree(kernel32) 
 	 return hfile
  endif

  boxtitle(object)
    
  ;download
  totalread=0
  bread=""
  btoread=10000
  databuf=binaryalloc(btoread)
  breadbuf=binaryalloc(4)
  bwrittenbuf=binaryalloc(4)
  while bread<>0
    r=dllcall(wininet,long:"InternetReadFile",long:openreqhandle,lpbinary:databuf,long:btoread,lpbinary:breadbuf) 
	 bread=BinaryPeek4(breadbuf,0)
    totalread=totalread+bread
    boxtext("%totalread% of %size%") 
    dllcall(kernel32,long:"WriteFile",long:hfile,lpbinary:databuf,long:bread,lpbinary:bwrittenbuf,lpnull)
  endwhile

  ;close file
  dllcall(kernel32,long:"_lclose",long:hfile)
  ;free mem
  binaryfree(databuf)
  binaryfree(breadbuf)
  binaryfree(bwrittenbuf)
  ;close ihandles
  dllcall(wininet,long:"InternetCloseHandle",long:tophandle)
  ;free dlls
  dllfree(wininet)
  dllfree(kernel32)

  if r==0 then return -2 ;timeout error
  else return stcode ;success

else
  dllcall(wininet,long:"InternetCloseHandle",long:tophandle)
  dllfree(wininet)
  dllfree(kernel32) 
  return stcode ;success (no download attempt <>200)
endif
#endfunction

;USAGE
;url="http://www.somesite.com/somedir/file.ext"
;host="www.somesite.com"
;object="/somedir/file.ext"
;localfile="c:\file.ext"
;
;boxopen("","") ;for progress display
;r=downloadfile(host,object,"","","",localfile,60)
;
;message("Result:",r)


Article ID:   W15730
File Created: 2003:05:13:11:29:52
Last Updated: 2003:05:13:11:29:52