web-dev-qa-db-fra.com

Comment créer un script de téléchargement FTP?

Je tente de créer un fichier de commandes pour télécharger un fichier sur le serveur FTP. Si je le tape manuellement, cela fonctionne bien, mais lorsque je lance le fichier de commandes, il s'arrête après sa connexion ... il est indiqué

connected to domain.com.

220 Microsoft ftp server

User(domain.com:(none)):

alors rien d'autre. Mais qu'est ce qu'il se passe ici?

Ci-dessous mon fichier de commandes:

ftp www.domainhere.com 

user useridhere

passwordhere

put test.txt

bye

pause
39
payling

C'est une idée raisonnable de vouloir programmer une session FTP comme l'affiche l'affiche originale, et c'est le genre de choses que Expect pourrait aider. Les fichiers batch sur Windows ne peuvent pas faire cela.

Mais plutôt que de faire cURL ou Expect, vous trouverez peut-être plus facile de scripter l'interaction FTP avec Powershell. C'est un modèle différent, en ce sens que vous n'écrivez pas directement le texte à envoyer au serveur FTP. À la place, vous utiliserez Powershell pour manipuler les objets qui génèrent le dialogue FTP pour vous.

Télécharger:

$File = "D:\Dev\somefilename.Zip"
$ftp = "ftp://username:[email protected]/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)

Télécharger:

$File = "c:\store\somefilename.Zip"
$ftp = "ftp://username:[email protected]/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)

Vous avez besoin de Powershell pour faire cela. Si vous n'êtes pas au courant, Powershell est un Shell comme cmd.exe qui exécute vos fichiers .bat. Mais Powershell exécute des fichiers .ps1 et est un peu plus puissant. Powershell est un complément gratuit à Windows et sera intégré aux futures versions de Windows. Obtenez-le ici .

Source: http://poshcode.org/1134

66
Cheeso

Créez un fichier de commandes avec vos commandes

c'est-à-dire: commands.txt

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

Ensuite, exécutez le client FTP à partir de la ligne de commande: ftp -s: commands.txt

Remarque: cela fonctionnera pour le client FTP Windows.

Edit: aurait dû avoir un saut de ligne après le nom d'utilisateur avant le mot de passe.

26
cbeuker

Les fichiers batch ne fonctionnent pas de cette façon. Ils ne font pas que "tout" taper - ils exécutent des commandes système, dans ce cas ftp, attendent leur retour et exécutent la commande suivante ... dans ce cas, l'interpréteur attend simplement ftp pour quitter.

Si vous devez utiliser la commande ftp, préparez un fichier de script (par exemple, commands.txt et courir ftp -s:commands.txt.

Mais en utilisant cURL, ou un script PHP/Perl/Python/n’importe quel autre peut être une meilleure idée.

6
grawity

J'ai fait ceci avec 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(" <DIR> ")) {
            [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
6
ruslander

Je sais que c'est une vieille question, mais je voulais ajouter quelque chose aux réponses déjà ici dans l'espoir d'aider quelqu'un d'autre.

Vous pouvez créer un script pour la commande ftp avec le -s:filename option. La syntaxe est juste une liste de commandes à transmettre au shell ftp, chacune terminée par une nouvelle ligne. Cette page contient une référence intéressante aux commandes pouvant être exécutées avec ftp.

Télécharger/Télécharger la structure complète du répertoire

L'utilisation de ftp normal ne fonctionne pas très bien lorsque vous devez copier l'intégralité de l'arborescence de répertoires vers ou depuis un site ftp. Donc, vous pouvez utiliser quelque chose comme ça pour gérer ces situations.

Ces scripts fonctionnent avec la commande Windows ftp et permettent de télécharger et de télécharger des répertoires entiers à partir d'une seule commande. Cela le rend assez autonome lorsqu'il est utilisé sur différents systèmes.

Fondamentalement, ils mappent la structure de répertoires à charger/télécharger, dump les commandes ftp correspondantes dans un fichier, puis exécutent ces commandes lorsque le mappage est terminé.

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
2
Bryan Way

J'avais un problème similaire - comme l'affiche originale, je voulais automatiser le téléchargement d'un fichier, mais je ne savais pas comment. Comme cela se trouve sur un terminal de registre dans le magasin de ma famille, je ne voulais pas installer PowerShell (bien que cela semble être une option facile), je voulais juste un simple fichier .bat pour le faire. C'est à peu près ce que grawity et un autre utilisateur ont dit; Je suis nouveau dans ce domaine, alors voici un exemple plus détaillé et une explication (merci également à http://www.howtogeek.com/howto/windows/how-to-automate-ftp-uploads-from- the-windows-command-line / qui explique comment le faire avec un seul fichier .bat.)

Vous avez essentiellement besoin de 2 fichiers - un .bat et un .txt. Le .bat indique à ftp.exe quels commutateurs utiliser. Le .txt donne une liste de commandes à ftp.exe. Dans le fichier texte, mettez ceci:

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

Gardez ça où vous voulez. Dans le fichier BAT, mettez:

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

Évidemment, changez le chemin après le -s: où que se trouve votre fichier texte. Supprimez la pause lorsque vous l'exécutez - c'est simplement pour que vous puissiez voir les erreurs. Bien sûr, vous pouvez utiliser "get" ou toute autre commande ftp dans le fichier .txt pour faire tout ce que vous devez faire.

Je ne suis pas sûr que vous ayez besoin de la commande lcd dans le fichier texte, comme je l'ai déjà dit, je ne suis pas habitué à utiliser la ligne de commande pour ce type de choses, mais cela fonctionne pour moi.

1
Josiah

J'ai eu ce même problème, et résolu avec une solution similaire à celle fournie par Cheeso, ci-dessus.

"ça ne marche pas, dit que le mot de passe est nécessaire, on l'a essayé de différentes façons"

Oui, c'est parce que les sessions FTP via un fichier de commande ne nécessitent pas que le nom d'utilisateur soit précédé de la chaîne "utilisateur". Laisse ça et essaie.

Vous pouvez également voir cela parce que votre fichier de commande FTP n'est pas correctement codé (ce bit m'a été aussi). C'est la partie de merde sur la génération d'un fichier de commande FTP au moment de l'exécution. La cmdlet de fichier externe de Powershell ne dispose pas d'une option d'encodage que Windows FTP acceptera (du moins pas que je pourrais trouver).

Quoi qu'il en soit, il est préférable de faire un WebClient.DownloadFile.

0
user180562

Ce script génère le fichier de commande, puis dirige le fichier de commande vers le programme ftp, créant un journal le long du chemin. Enfin, imprimez le fichier bat original, les fichiers de commande et le journal de cette session.

@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 
0
ken klein

Essayez manuellement:

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