¿Cómo puedo descargar un archivo con archivo por lotes sin usar herramientas externas?

Primero para aclarar que esta pregunta está dirigida a la (s) descarga (s) de HTTP (s) .Puede que FTP le haga (y responda) otra pregunta. Aquí hay algunas preguntas similares , pero quiero ser más preciso.

Además de excluir las herramientas externas, quiero que la (s) solución (es) sea (n) aplicable (s) para los tipos más amplios posibles de máquinas de Windows (incluyendo XP, Win2003, Vista que aún tienen una participación lo suficientemente grande). Además, como WSH es una de las opciones posibles, prefiero no usar archivos temporales y todo lo que se empaqueta en un solo archivo .bat (lo cual es posible tanto con jscript como con vbscript).

¿Cuáles son los posibles enfoques?

  1. Solución de lote “pura” con BITSADMIN – una utilidad de línea de comandos disponible en todas las máquinas de Windows. No es muy conveniente, pero es la única opción donde no se debe utilizar ningún otro lenguaje de scripting.
  2. Uso de WSH: son posibles tres enfoques: WinHTTP , MSXML2.XMLHTTP , InternetExlorer.Application : todos ellos son objetos ActiveX accesibles en el orden en que los prefiero. WinHTTP y MSXML2.XMLHTTP son bastante similares en sus capacidades, pero WinHTTP tiene una reputación de más estable.InternetExlorer.Application es, de hecho, solo el explorador de Internet accesible a través del objeto ActiveX y algunos elementos de la IU son inevitables (¿verdad?) así que me saltearé este.
  3. Usando .NET – Es posible crear un archivo por lotes híbrido con los tres comstackdores .NET predeterminados (Jscript.net, VB.Net, C #) con Jscript.net no hay mensajes de error redundantes, así que lo preferiré. Si ignore el hecho de que hay un .exe comstackdo, todo el código está en un archivo, por lo que, según yo, esto se ajusta a los requisitos :-). Con .NET podemos usar System.Net.WebClient o System.Net.HttpWebRequest (el WebClient). depende de ello) o
    System.Web.HttpRequest, pero por ahora solo publicaré la solución System.Net.WebClient. Y aún más, los mismos objetos ActiveX accesibles con WSH están disponibles aquí. Así que hay muchas maneras de descargar un archivo con .Net.May en el futuro, actualizaré mi respuesta. De todos modos, solo el Webclient está especialmente diseñado para descargar.
  4. El uso de powershell tiene las mismas posibilidades que .NET, pero tiene menos posibilidades de instalarse en todas las máquinas que puede encontrar. Así que también me voy a saltar este.

    Las respuestas. Todas las secuencias de comandos se deben guardar con extensiones .bat / .cmd y se pueden usar directamente como scripts por lotes.

    1) Certutuil :

     certutil.exe -urlcache -split -f "https://download.sysinternals.com/files/PSTools.zip" pstools.zip 

    Se puede abusar del comando CertUtil para descargar un archivo desde Internet. Está disponible por defecto en Windows desde Vista. Para WinXP Server 2003 se necesitan herramientas de administración.

    2) Bitsadmin :

    la forma más simple posible de usarlo

     bitsadmin /transfer myDownloadJob /download /priority normal http://downloadsrv/10mb.zip c:\10mb.zip 

    O (eventualmente necesitará esto si quiere agregar credenciales, proxy y etc.)

      @echo off setlocal :: uses bitsadmin utility to download a file :: bitsadmin is not available in winXP Home edition :: the only way to download a file with 'pure' batch :download if "%2" equ "" ( call :help exit /b 5 ) if "%1" equ "" ( call :help exit /b 6 ) set url=%~1 set file=%~2 rem ---- if "%~3" NEQ "" ( set /A timeout=%~3 ) else ( set timeout=5 ) bitsadmin /cancel download >nul bitsadmin /create /download download >nul call bitsadmin /addfile download "%url%" "%CD%\%file%" >nul bitsadmin /resume download >nul bitsadmin /setproxysettings download AUTODETECT >nul set /a attempts=0 :repeat set /a attempts +=1 if "%attempts%" EQU "10" ( echo TIMED OUT endlocal exit /b 1 ) bitsadmin /info download /verbose | find "STATE: ERROR" >nul 2>&1 && endlocal && bitsadmin /cancel download && echo SOME KIND OF ERROR && exit /b 2 bitsadmin /info download /verbose | find "STATE: SUSPENDED" >nul 2>&1 && endlocal && bitsadmin /cancel download &&echo FILE WAS NOT ADDED && exit /b 3 bitsadmin /info download /verbose | find "STATE: TRANSIENT_ERROR" >nul 2>&1 && endlocal && bitsadmin /cancel download &&echo TRANSIENT ERROR && exit /b 4 bitsadmin /info download /verbose | find "STATE: TRANSFERRED" >nul 2>&1 && goto :finishing w32tm /stripchart /computer:localhost /period:1 /dataonly /samples:%timeout% >nul 2>&1 goto :repeat :finishing bitsadmin /complete download >nul echo download finished endlocal goto :eof :help echo %~n0 url file [timeout] echo. echo url - the source for download echo file - file name in local directory where the file will be stored echo timeout - number in seconds between each check if download is complete (attempts are 10) echo. goto :eof 

    3) – WinHttp y WSH (las opciones SSL / certificado y Proxy nunca se han probado …). Aquí hay un script listo para usar que usa WinHttpRequest . Puede realizar toda una serie de solicitudes http y también puede usarse para descargar archivos (archivos no demasiado grandes). Si lo necesita, también puede agregar sus propios encabezados de autenticación.

     call winhhtpjs.bat https://example.com/files/some.zip -saveTo c:\somezip.zip 

    4) MSXML2.XMLHTTP y WSH (mejor uso de WinHTTP) (SSL / certificado y las opciones de Proxy nunca se han probado …)

     @if (@X)==(@Y) @end /* JScript comment @echo off rem :: the first argument is the script name as it will be used for proper help message cscript //E:JScript //nologo "%~f0" "%~nx0" %* exit /b %errorlevel% @if (@X)==(@Y) @end JScript comment */ // used resources //http://www.codeproject.com/Tips/506439/Downloading-files-with-VBScript //http://blogs.msdn.com/b/xmlteam/archive/2006/10/23/using-the-right-version-of-msxml-in-internet-explorer.aspx //https://msdn.microsoft.com/en-us/library/ie/ms535874(v=vs.85).aspx //https://msdn.microsoft.com/en-us/library/aa923283.aspx //https://msdn.microsoft.com/en-us/library/ms759148(v=vs.85).aspx //https://msdn.microsoft.com/en-us/library/ms759148(v=vs.85).aspx //https://msdn.microsoft.com/en-us/library/ms760236(v=vs.85).aspx //http://stackoverflow.com/questions/20712635/providing-authentication-info-via-msxml2-serverxmlhttp //https://msdn.microsoft.com/en-us/library/ms763680(v=vs.85).aspx //https://msdn.microsoft.com/en-us/library/ms757849(v=vs.85).aspx //http://fm4dd.com/programming/shell/microsoft-vbs-http-download.htm //http://stackoverflow.com/questions/11573022/vba-serverxmlhttp-https-request-with-self-signed-certificate //http://www.qtcentre.org/threads/44629-Using-XMLHttpRequest-for-HTTPS-Post-to-server-with-SSL-certificate // global variables and constants var ARGS = WScript.Arguments; var scriptName=ARGS.Item(0); var url=""; var saveTo=""; var user=0; var pass=0; var proxy=0; var bypass=""; var proxy_user=0; var proxy_pass=0; var certificate=0; var force=true; //ActiveX objects //Use the right version of MSXML /*var progIDs = [ 'Msxml2.DOMDocument.6.0', 'Msxml2.DOMDocument.5.0', 'Msxml2.DOMDocument.4.0', 'Msxml2.DOMDocument.3.0', 'Msxml2.DOMDocument' ] for (var i = 0; i < progIDs.length; i++) { try { var XMLHTTPObj = new ActiveXObject(progIDs[i]); }catch (ex) { } } if typeof XMLHTTPObj === 'undefined'{ WScript.Echo ("You are using too ancient windows or you have no installed IE"); WScript.Quit(1); }*/ var XMLHTTPObj = new ActiveXObject("MSXML2.XMLHTTP"); var FileSystemObj = new ActiveXObject("Scripting.FileSystemObject"); var AdoDBObj = new ActiveXObject("ADODB.Stream"); function printHelp(){ WScript.Echo(scriptName + " - downloads a file through HTTP"); WScript.Echo(scriptName + " url localfile [-force yse|no] [-user username -password password] [-proxy proxyserver:port -bypass bypass_list]"); WScript.Echo(" [-proxyuser proxy_username -proxypassword proxy_password] [-certificate certificateString]"); WScript.Echo("-force - decide to not or to overwrite if the local exists"); WScript.Echo("proxyserver:port - the proxy server"); WScript.Echo("bypass- bypass list can be \"\" if you don't need it"); WScript.Echo("proxy_user , proxy_password - credentials for proxy server"); WScript.Echo("user , password - credentials for the server"); WScript.Echo("certificate - location of SSL certificate"); WScript.Echo("Example:"); WScript.Echo(scriptName +" http://somelink.com/somefile.zip c:\\somefile.zip -certificate \"LOCAL_MACHINE\\Personal\\My Middle-Tier Certificate\""); } function parseArgs(){ // if (ARGS.Length < 3) { WScript.Echo("insufficient arguments"); printHelp(); WScript.Quit(43); } url=ARGS.Item(1); saveTo=ARGS.Item(2); if(ARGS.Length % 2 != 1) { WScript.Echo("illegal arguments"); printHelp(); WScript.Quit(44); } for (var i=3;i https://en.wikipedia.org/wiki/List_of_HTTP_status_codes"); WScript.Quit(status); } writeFile(file,XMLHTTPObj.ResponseBody); } function main(){ parseArgs(); download(url,saveTo); } main(); 

    5) .NET y webclient (Aquí no hay ninguna opción de SSL. Trataré de agregarlo. Las opciones de Poxy nunca se han probado)

     @if (@X)==(@Y) @end /* JScript comment @echo off setlocal for /f "tokens=* delims=" %%v in ('dir /b /s /a:-d /o:-n "%SystemRoot%\Microsoft.NET\Framework\*jsc.exe"') do ( set "jsc=%%v" ) ::if not exist "%~n0.exe" ( "%jsc%" /nologo /out:"%~n0.exe" "%~dpsfnx0" ::) %~n0.exe %* endlocal & exit /b %errorlevel% */ //todo SSL Support //todo Better help message //todo check if local file exists import System; import System.Net.WebClient; import System.Net.NetworkCredential; import System.Net.WebProxy; import System.Uri; import System.Security.Cryptography.X509Certificates; var arguments:String[] = Environment.GetCommandLineArgs(); var url=0; var toFile=0; var force=true; var user=0; var password=0; var proxy=0; var bypass=0; var proxy_user=0; var proxy_pass=0; var certificate=0; function printHelp(){ Console.WriteLine(arguments[0] + "download from url to a file"); Console.WriteLine(arguments[0] + "  [-user user -password password] [-proxy proxy] [-proxy_user proxy.user -proxy_pass proxy.pass]"); } function parseArgs(){ if (arguments.length < 3) { Console.WriteLine("Wrong arguments"); printHelp(); Environment.Exit(1); } if (arguments.length %2 != 1) { Console.WriteLine("Wrong number arguments"); printHelp(); Environment.Exit(2); } url=arguments[1]; toFile=arguments[2]; for (var i=3;i