Articles

  • Downloading large files with VBScript

    Downloading (well doing anything really) is a pain with VBScript, but recently, while writing a script to download, install and update apps from the net, I discovered that the MSXML2.XMLHTTP COM object can't download large files. Well, it isn't necessarily large files that break it, but files that take a while to download. There seems to be an in-built timeout, and once that has been exceeded, it will cut the connection.

    The only evidence of this is the status code - it will return 0.

    Turns out you need to use MSXML2.ServerXMLHTTP in order to set timeouts to a longer period. The relevant sub-routine is setTimeouts. Note this doesn't seem to be a timeout in the traditional sense - this timeout value specifies how long the entire response can take, not how long to wait if there is no response from the server.

    Below is some code that wraps all this in a neat function.

    Function Download ( ByVal strUrl, ByVal strDestPath, ByVal overwrite )
        Dim intStatusCode, objXMLHTTP, objADOStream, objFSO
        Set objFSO = CreateObject("Scripting.FileSystemObject")
    
        ' if the file exists already, and we're not overwriting, quit now
        If Not overwrite And objFSO.FileExists(strDestPath) Then
            WScript.Echo "Already exists - " & strDestPath
            Download = True
            Exit Function
        End If
    
        WScript.Echo "Downloading " & strUrl & " to " & strDestPath
    
        ' Fetch the file
        ' need to use ServerXMLHTTP so can set timeouts for downloading large files
        Set objXMLHTTP = CreateObject("MSXML2.ServerXMLHTTP")
        objXMLHTTP.open "GET", strUrl, false
        objXMLHTTP.setTimeouts 1000 * 60 * 1, 1000 * 60 * 1, 1000 * 60 * 1, 1000 * 60 * 7
        objXMLHTTP.send()
    
        intStatusCode = objXMLHTTP.Status
    
        If intStatusCode = 200 Then
            Set objADOStream = CreateObject("ADODB.Stream")
            objADOStream.Open
            objADOStream.Type = 1 'adTypeBinary
            objADOStream.Write objXMLHTTP.ResponseBody
            objADOStream.Position = 0    'Set the stream position to the start
    
            'If the file already exists, delete it.
            'Otherwise, place the file in the specified location
            If objFSO.FileExists(strDestPath) Then objFSO.DeleteFile strDestPath
    
            objADOStream.SaveToFile strDestPath
            objADOStream.Close
    
            Set objADOStream = Nothing
        End If
    
        Set objXMLHTTP = Nothing
        Set objFSO = Nothing
    
        WScript.Echo "Status code: " & intStatusCode & VBNewLine 
    
        If intStatusCode = 200 Then
            Download = True
        Else
            Download = False
        End If
    End Function
     

Comments

1.

Great!  Just what I was looking for and far better than what I was using - "WinHttp.WinHttpRequest.5.1"

Posted by Kel, 19th April 2015 11:21 AM
 
2.

Why couldn't this page pop up on Google sooner, I'll have to give this a shot when I get back! Thanks

Posted by Duckboy81, 8th September 2015 10:21 AM
 

Leave a comment