5

i'm trying to automate a file download with Windows Script Host (JScript). i see ADODB.Stream has an Open method whose documentation makes it seem like it should be possible to open a HTTP URL and stream the response body:

var url = 'http://example.com/example.tar.gz';
var path = 'example.tar.gz';

var input = WScript.CreateObject('ADODB.Stream');

input.Open(url);
input.SaveToFile(path);
input.Close();

But it bombs on the Open call with

(null): Object or data matching the name, range, or selection criteria was not found within the scope of this operation.

1
  • 2
    kids, the only correct answer to any question starting with "How do I use WSH to..." is DON'T. this question was just a tip of the iceberg of problems i had back then, decided to go with python and its win32api, and while it wasn't stellar (docs), i was able to automate quite a bit in windows without losing my sanity. Commented Jun 25, 2013 at 15:28

4 Answers 4

8

Here is the download code in JScript. Also added some references to API information.

var Source = WScript.Arguments.Item(0);
var Target = WScript.Arguments.Item(1);
var Object = WScript.CreateObject('MSXML2.XMLHTTP');

Object.Open('GET', Source, false);
Object.Send();

if (Object.Status == 200)
{
    // Create the Data Stream
    var Stream = WScript.CreateObject('ADODB.Stream');

    // Establish the Stream
    Stream.Open();
    Stream.Type = 1; // adTypeBinary
    Stream.Write(Object.ResponseBody);
    Stream.Position = 0;

    // Create an Empty Target File
    var File = WScript.CreateObject('Scripting.FileSystemObject');
    if (File.FileExists(Target))
    {
        File.DeleteFile(Target);
    }

    // Write the Data Stream to the File
    Stream.SaveToFile(Target, 2); // adSaveCreateOverWrite
    Stream.Close();
}

ADODB Stream:

Scripting.FileSystemObject:

Sign up to request clarification or add additional context in comments.

1 Comment

i can't confirm that this actually works as i don't work with windows anymore (hurray!) and in the end i used python anyway. it does look sane and it is jScript, so i'm accepting it.
4

You're on the right track.

You should be using the XMLHTTPRequest Object to communicate with the server. It's sort of like "curl" for Windows Script. Once the data is read from the remote server, you can write it into an ADODB stream and manipulate it within your script. In your case, writing to a file using the FileSystemObject seems like the most logical course of action.

So your script might look something like this:

' Set your settings
strFileURL = "http://www.domain.com/file.zip"
strSavePath = "C:\somefolder\"

' Send an HTTP request for the file
Set objXMLHTTP = CreateObject("MSXML2.XMLHTTP")

objXMLHTTP.open "GET", strFileURL, false
objXMLHTTP.send()

' If the server responds with "OK"...
If objXMLHTTP.Status = 200 Then
    ' Create a stream object to write downloaded data to
    Set objADOStream = CreateObject("ADODB.Stream")
    objADOStream.Open
    objADOStream.Type = 1 'adTypeBinary

    objADOStream.Write objXMLHTTP.ResponseBody
    objADOStream.Position = 0

    ' Create an empty file on disk
    Set objFso = Createobject("Scripting.FileSystemObject")
    ' Make sure we don't have any name collision...
    If objFso.Fileexists(strSavePath) Then objFSO.DeleteFile strSavePath
    Set objFso = Nothing

    ' Write the stream data to file
    objADOStream.SaveToFile strSavePath
    objADOStream.Close
    Set objADOStream = Nothing
End if

Set objXMLHTTP = Nothing

1 Comment

That's VBscript, not JScript
2

Converted the above code to JavaScript. This appears to work for me. Recommend adding a try catch block to the caller. Also, converted to async. I've used this code to save some 90 files at the same time. Since the delete file (necessary as the overwrite fails) is synchronous, it is better moved to a separate function for multiple files.

function saveFile(sSourceUrl, sDestFile) {
    var objXMLHTTP = new ActiveXObject("MSXML2.XMLHTTP");
    objXMLHTTP.onreadystatechange=function() {
        if (objXMLHTTP.readyState === 4) {
            var objADOStream = new ActiveXObject("ADODB.Stream");
            objADOStream.open();
            objADOStream.type = 1; // Binary
            objADOStream.write(objXMLHTTP.ResponseBody);
            objADOStream.position = 0;
            objADOStream.saveToFile(sDestFile, 2);
            objADOStream.close();
        }
    };

    objXMLHTTP.open("GET", sSourceUrl, false);
    objXMLHTTP.send();
}

1 Comment

Use objADOStream.saveToFile(sDestFile, 2); // adSaveCreateOverWrite to get rid of the need for file deletion.
1

Your URL needs to be in this format:

URL=scheme://server/folder

2 Comments

Would you care to explain why?
See MSDN Open Method (ADO Stream). This is saying that the source should be a string formatted like var url = 'URL=http://example.com/example.tar.gz';

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.