¿Cómo se progtwig la carga y descarga de FTP?

Estoy intentando hacer un archivo por lotes para cargar un archivo al servidor ftp. Si lo escribo manualmente, funciona bien, pero cuando ejecuto el archivo por lotes, se detiene después de que está conectado … dice

connected to domain.com. 220 microsoft ftp server User(domain.com:(none)): 

entonces nada más. ¿Qué diablos está pasando aquí?

Debajo está mi archivo por lotes:

 ftp www.domainhere.com user useridhere passwordhere put test.txt bye pause 

Es una idea razonable querer crear secuencias de comandos de una sesión de FTP de la forma en que el cartel original se imaginó, y ese es el tipo de cosas en las que esperaría ayuda. Los archivos por lotes en Windows no pueden hacer esto.

Pero en lugar de ejecutar cURL o Expect, puede que le resulte más fácil realizar un script de la interacción de FTP con Powershell. Es un modelo diferente, ya que no está escribiendo directamente el texto para enviarlo al servidor FTP. En cambio, utilizará Powershell para manipular objetos que generen el diálogo FTP para usted.

Subir:

 $File = "D:\Dev\somefilename.zip" $ftp = "ftp://username:password@example.com/pub/incoming/somefilename.zip" "ftp url: $ftp" $webclient = New-Object System.Net.WebClient $uri = New-Object System.Uri($ftp) "Uploading $File..." $webclient.UploadFile($uri, $File) 

Descargar:

 $File = "c:\store\somefilename.zip" $ftp = "ftp://username:password@example.com/pub/outbound/somefilename.zip" "ftp url: $ftp" $webclient = New-Object System.Net.WebClient $uri = New-Object System.Uri($ftp) "Downloading $File..." $webclient.DownloadFile($uri, $File) 

Necesitas Powershell para hacer esto. Si no lo sabe, Powershell es un shell como cmd.exe que ejecuta sus archivos .bat. Pero Powershell ejecuta archivos .ps1 y es bastante más potente. Powershell es un complemento gratuito para Windows y se incorporará a futuras versiones de Windows. Consíguelo aquí .

Fuente: http://poshcode.org/1134

Crea un archivo de comando con tus comandos

es decir: comandos.txt

 open www.domainhere.com user useridhere passwordhere put test.txt bye 

A continuación, ejecute el cliente FTP desde la línea de comando: ftp -s: commands.txt

Nota: Esto funcionará para el cliente FTP de Windows.

Editar: debería haber tenido un salto de línea después del nombre de usuario antes de la contraseña.

Los archivos por lotes no funcionan de esa manera. No solo “escriben” todo: ejecutan comandos del sistema, en este caso ftp , esperan a que vuelvan, y ejecutan el siguiente comando … entonces, en este caso, el intérprete simplemente está esperando que ftp salga.

Si debe usar el comando ftp , prepare un archivo de script (por ejemplo, commands.txt y ejecute ftp -s:commands.txt .

Pero usar cURL , o un script PHP / Perl / Python / lo que sea, puede ser una mejor idea.

He hecho esto con PowerShell :

 function DownloadFromFtp($destination, $ftp_uri, $user, $pass){ $dirs = GetDirecoryTree $ftp_uri $user $pass foreach($dir in $dirs){ $path = [io.path]::Combine($destination,$dir) if ((Test-Path $path) -eq $false) { "Creating $path ..." New-Item -Path $path -ItemType Directory | Out-Null }else{ "Exists $path ..." } } $files = GetFilesTree $ftp_uri $user $pass foreach($file in $files){ $source = [io.path]::Combine($ftp_uri,$file) $dest = [io.path]::Combine($destination,$file) "Downloading $source ..." Get-FTPFile $source $dest $user $pass } } function UploadToFtp($artifacts, $ftp_uri, $user, $pass){ $webclient = New-Object System.Net.WebClient $webclient.Credentials = New-Object System.Net.NetworkCredential($user,$pass) foreach($item in Get-ChildItem -recurse $artifacts){ $relpath = [system.io.path]::GetFullPath($item.FullName).SubString([system.io.path]::GetFullPath($artifacts).Length + 1) if ($item.Attributes -eq "Directory"){ try{ Write-Host Creating $item.Name $makeDirectory = [System.Net.WebRequest]::Create($ftp_uri+$relpath); $makeDirectory.Credentials = New-Object System.Net.NetworkCredential($user,$pass) $makeDirectory.Method = [System.Net.WebRequestMethods+FTP]::MakeDirectory; $makeDirectory.GetResponse(); }catch [Net.WebException] { Write-Host $item.Name probably exists ... } continue; } "Uploading $item..." $uri = New-Object System.Uri($ftp_uri+$relpath) $webclient.UploadFile($uri, $item.FullName) } } function Get-FTPFile ($Source,$Target,$UserName,$Password) { $ftprequest = [System.Net.FtpWebRequest]::create($Source) $ftprequest.Credentials = New-Object System.Net.NetworkCredential($username,$password) $ftprequest.Method = [System.Net.WebRequestMethods+Ftp]::DownloadFile $ftprequest.UseBinary = $true $ftprequest.KeepAlive = $false $ftpresponse = $ftprequest.GetResponse() $responsestream = $ftpresponse.GetResponseStream() $targetfile = New-Object IO.FileStream ($Target,[IO.FileMode]::Create) [byte[]]$readbuffer = New-Object byte[] 1024 do{ $readlength = $responsestream.Read($readbuffer,0,1024) $targetfile.Write($readbuffer,0,$readlength) } while ($readlength -ne 0) $targetfile.close() } #task ListFiles { # # $files = GetFilesTree 'ftp://127.0.0.1/' "web" "web" # $files | ForEach-Object {Write-Host $_ -foregroundcolor cyan} #} function GetDirecoryTree($ftp, $user, $pass){ $creds = New-Object System.Net.NetworkCredential($user,$pass) $files = New-Object "system.collections.generic.list[string]" $folders = New-Object "system.collections.generic.queue[string]" $folders.Enqueue($ftp) while($folders.Count -gt 0){ $fld = $folders.Dequeue() $newFiles = GetAllFiles $creds $fld $dirs = GetDirectories $creds $fld foreach ($line in $dirs){ $dir = @($newFiles | Where { $line.EndsWith($_) })[0] [void]$newFiles.Remove($dir) $folders.Enqueue($fld + $dir + "/") [void]$files.Add($fld.Replace($ftp, "") + $dir + "/") } } return ,$files } function GetFilesTree($ftp, $user, $pass){ $creds = New-Object System.Net.NetworkCredential($user,$pass) $files = New-Object "system.collections.generic.list[string]" $folders = New-Object "system.collections.generic.queue[string]" $folders.Enqueue($ftp) while($folders.Count -gt 0){ $fld = $folders.Dequeue() $newFiles = GetAllFiles $creds $fld $dirs = GetDirectories $creds $fld foreach ($line in $dirs){ $dir = @($newFiles | Where { $line.EndsWith($_) })[0] [void]$newFiles.Remove($dir) $folders.Enqueue($fld + $dir + "/") } $newFiles | ForEach-Object { $files.Add($fld.Replace($ftp, "") + $_) } } return ,$files } function GetDirectories($creds, $fld){ $dirs = New-Object "system.collections.generic.list[string]" $operation = [System.Net.WebRequestMethods+Ftp]::ListDirectoryDetails $reader = GetStream $creds $fld $operation while (($line = $reader.ReadLine()) -ne $null) { if ($line.Trim().ToLower().StartsWith("d") -or $line.Contains("  ")) { [void]$dirs.Add($line) } } $reader.Dispose(); return ,$dirs } function GetAllFiles($creds, $fld){ $newFiles = New-Object "system.collections.generic.list[string]" $operation = [System.Net.WebRequestMethods+Ftp]::ListDirectory $reader = GetStream $creds $fld $operation while (($line = $reader.ReadLine()) -ne $null) { [void]$newFiles.Add($line.Trim()) } $reader.Dispose(); return ,$newFiles } function GetStream($creds, $url, $meth){ $ftp = [System.Net.WebRequest]::Create($url) $ftp.Credentials = $creds $ftp.Method = $meth $response = $ftp.GetResponse() return New-Object IO.StreamReader $response.GetResponseStream() } Export-ModuleMember UploadToFtp, DownLoadFromFtp 

Sé que esta es una vieja pregunta, pero quería agregar algo a las respuestas que ya están aquí con la esperanza de ayudar a alguien más.

Puede ftp comando ftp con la opción -s:filename . La syntax es solo una lista de comandos para pasar al shell ftp , cada uno terminado por una nueva línea. Esta página tiene una buena referencia a los comandos que se pueden realizar con ftp .

Cargar / Descargar toda la estructura del directorio

Usar el ftp normal no funciona muy bien cuando necesita tener un árbol de directorios completo copiado ao desde un sitio ftp. Entonces podrías usar algo como esto para manejar esas situaciones.

Estos scripts funcionan con el comando ftp Windows y permiten cargar y descargar directorios completos desde un solo comando. Esto lo hace bastante autosuficiente cuando se usa en diferentes sistemas.

Básicamente lo que hacen es mapear la estructura del directorio que se va a subir / descargar, volcar los comandos ftp correspondientes a un archivo, luego ejecutar esos comandos cuando la asignación ha terminado.

ftpupload.bat

 @echo off SET FTPADDRESS=%1 SET FTPUSERNAME=%2 SET FTPPASSWORD=%3 SET LOCALDIR=%~f4 SET REMOTEDIR=%5 if "%FTPADDRESS%" == "" goto FTP_UPLOAD_USAGE if "%FTPUSERNAME%" == "" goto FTP_UPLOAD_USAGE if "%FTPPASSWORD%" == "" goto FTP_UPLOAD_USAGE if "%LOCALDIR%" == "" goto FTP_UPLOAD_USAGE if "%REMOTEDIR%" == "" goto FTP_UPLOAD_USAGE :TEMP_NAME set TMPFILE=%TMP%\%RANDOM%_ftpupload.tmp if exist "%TMPFILE%" goto TEMP_NAME SET INITIALDIR=%CD% echo user %FTPUSERNAME% %FTPPASSWORD% > %TMPFILE% echo bin >> %TMPFILE% echo lcd %LOCALDIR% >> %TMPFILE% cd %LOCALDIR% setlocal EnableDelayedExpansion echo mkdir !REMOTEDIR! >> !TMPFILE! echo cd %REMOTEDIR% >> !TMPFILE! echo mput * >> !TMPFILE! for /d /r %%d in (*) do ( set CURRENT_DIRECTORY=%%d set RELATIVE_DIRECTORY=!CURRENT_DIRECTORY:%LOCALDIR%=! echo mkdir "!REMOTEDIR!/!RELATIVE_DIRECTORY:~1!" >> !TMPFILE! echo cd "!REMOTEDIR!/!RELATIVE_DIRECTORY:~1!" >> !TMPFILE! echo mput "!RELATIVE_DIRECTORY:~1!\*" >> !TMPFILE! ) echo quit >> !TMPFILE! endlocal EnableDelayedExpansion ftp -n -i "-s:%TMPFILE%" %FTPADDRESS% del %TMPFILE% cd %INITIALDIR% goto FTP_UPLOAD_EXIT :FTP_UPLOAD_USAGE echo Usage: ftpupload [address] [username] [password] [local directory] [remote directory] echo. :FTP_UPLOAD_EXIT set INITIALDIR= set FTPADDRESS= set FTPUSERNAME= set FTPPASSWORD= set LOCALDIR= set REMOTEDIR= set TMPFILE= set CURRENT_DIRECTORY= set RELATIVE_DIRECTORY= @echo on 

ftpget.bat

 @echo off SET FTPADDRESS=%1 SET FTPUSERNAME=%2 SET FTPPASSWORD=%3 SET LOCALDIR=%~f4 SET REMOTEDIR=%5 SET REMOTEFILE=%6 if "%FTPADDRESS%" == "" goto FTP_UPLOAD_USAGE if "%FTPUSERNAME%" == "" goto FTP_UPLOAD_USAGE if "%FTPPASSWORD%" == "" goto FTP_UPLOAD_USAGE if "%LOCALDIR%" == "" goto FTP_UPLOAD_USAGE if not defined REMOTEDIR goto FTP_UPLOAD_USAGE if not defined REMOTEFILE goto FTP_UPLOAD_USAGE :TEMP_NAME set TMPFILE=%TMP%\%RANDOM%_ftpupload.tmp if exist "%TMPFILE%" goto TEMP_NAME echo user %FTPUSERNAME% %FTPPASSWORD% > %TMPFILE% echo bin >> %TMPFILE% echo lcd %LOCALDIR% >> %TMPFILE% echo cd "%REMOTEDIR%" >> %TMPFILE% echo mget "%REMOTEFILE%" >> %TMPFILE% echo quit >> %TMPFILE% ftp -n -i "-s:%TMPFILE%" %FTPADDRESS% del %TMPFILE% goto FTP_UPLOAD_EXIT :FTP_UPLOAD_USAGE echo Usage: ftpget [address] [username] [password] [local directory] [remote directory] [remote file pattern] echo. :FTP_UPLOAD_EXIT set FTPADDRESS= set FTPUSERNAME= set FTPPASSWORD= set LOCALDIR= set REMOTEFILE= set REMOTEDIR= set TMPFILE= set CURRENT_DIRECTORY= set RELATIVE_DIRECTORY= @echo on 

Estaba teniendo un problema similar: al igual que el póster original, quería automatizar la carga de un archivo, pero no pude entender cómo. Como esto está en una terminal de registro en la tienda de mi familia, no quería instalar PowerShell (aunque parece una opción fácil), solo quería un archivo .bat simple para hacer esto. Esto es más o menos lo que dijo grawity y otro usuario; Soy nuevo en esto, así que aquí hay un ejemplo y una explicación más detallados (gracias también a http://www.howtogeek.com/howto/windows/how-to-automate-ftp-uploads-from-the- windows- línea de comandos / quién explica cómo hacerlo con solo un archivo .bat.)

Esencialmente necesitas 2 archivos: uno .bat y uno .txt. El .bat le dice a http://ftp.exe qué cambios usar. El archivo .txt proporciona una lista de comandos para http://ftp.exe. En el archivo de texto, coloca esto:

 username password cd whereverYouWantToPutTheFile lcd whereverTheFileComesFrom put C:\InventoryExport\inventory.test (or your file path) bye 

Guarde eso donde quiera. En el archivo BAT pon:

 ftp.exe -s:C:\Windows\System32\test.txt destinationIP pause 

Obviamente, cambie la ruta después de -s: donde sea que esté su archivo de texto. Elimina la pausa cuando la ejecutas, solo para que puedas ver los errores. Por supuesto, puede usar “get” o cualquier otro comando ftp en el archivo .txt para hacer lo que necesite hacer.

No estoy seguro de que necesite el comando lcd en el archivo de texto, como dije que soy nuevo en el uso de la línea de comandos para este tipo de cosas, pero esto está funcionando para mí.

Tuve el mismo problema y lo resolví con una solución similar a la que proporcionó Cheeso anteriormente.

“no funciona, dice que la contraseña es necesaria, lo intenté de dos maneras diferentes”

Sí, eso es porque las sesiones de FTP a través de un archivo de comandos no requieren que el nombre de usuario tenga el prefijo “usuario”. Suelta eso y pruébalo.

O bien, podría estar viendo esto porque su archivo de comando FTP no está codificado correctamente (eso también me mordió). Esa es la parte mala de generar un archivo de comando FTP en tiempo de ejecución. El cmdlet out-file de Powershell no tiene una opción de encoding que acepte el FTP de Windows (al menos no uno que yo pueda encontrar).

De todos modos, como hacer un WebClient.DownloadFile es el camino a seguir.

Pruebe de forma manual:

 $ ftp www.domainhere.com > useridhere > passwordhere > put test.txt > bye > pause 

Este script genera el archivo de comando y luego canaliza el archivo de comando al progtwig ftp, creando un registro a lo largo del camino. Finalmente, imprima el archivo bat original, los archivos de comando y el registro de esta sesión.

 @echo on @echo off > %0.ftp ::== GETmy!dir.bat >> %0.ftp echo a00002t >> %0.ftp echo iasdad$2 >> %0.ftp echo help >> %0.ftp echo prompt >> %0.ftp echo ascii >> %0.ftp echo !dir REPORT.CP1C.ROLLEDUP.TXT >> %0.ftp echo get REPORT.CP1C.ROLLEDUP.TXT >> %0.ftp echo !dir REPORT.CP1C.ROLLEDUP.TXT >> %0.ftp echo ************************************************* >> %0.ftp echo !dir CONTENT.CP1C.ROLLEDUP.TXT >> %0.ftp echo get CONTENT.CP1C.ROLLEDUP.TXT >> %0.ftp echo !dir CONTENT.CP1C.ROLLEDUP.TXT >> %0.ftp echo ************************************************* >> %0.ftp echo !dir WORKLOAD.CP1c.ROLLEDUP.TXT >> %0.ftp echo get WORKLOAD.CP1C.ROLLEDUP.TXT >> %0.ftp echo !dir WORKLOAD.CP1C.ROLLEDUP.TXT >> %0.ftp echo ************************************************* >> %0.ftp echo !dir REPORT.TMMC.ROLLEDUP.TXT >> %0.ftp echo get REPORT.TMMC.ROLLEDUP.TXT >> %0.ftp echo !dir REPORT.TMMC.ROLLEDUP.TXT >> %0.ftp echo ************************************************* >> %0.ftp echo !dir CONTENT.TMMC.ROLLEDUP.TXT >> %0.ftp echo get CONTENT.TMMC.ROLLEDUP.TXT >> %0.ftp echo !dir CONTENT.TMMC.ROLLEDUP.TXT >> %0.ftp echo ************************************************** >> %0.ftp echo !dir WORKLOAD.TMMC.ROLLEDUP.TXT >> %0.ftp echo get WORKLOAD.TMMC.ROLLEDUP.TXT >> %0.ftp echo !dir WORKLOAD.TMMC.ROLLEDUP.TXT >> %0.ftp echo quit ftp -d -v -s:%0.ftp 150.45.12.18 > %0.log type %0.bat type %0.ftp type %0.log