Как написать сценарий загрузки и выгрузки по FTP?
Я пытаюсь создать командный файл для загрузки файла на FTP-сервер. Если я ввожу его вручную, он работает нормально, но когда я запускаю командный файл, он останавливается после подключения... он говорит
connected to domain.com.
220 microsoft ftp server
User(domain.com:(none)):
тогда больше ничего. Какого черта здесь происходит?
Ниже мой пакетный файл:
ftp www.domainhere.com
user useridhere
passwordhere
put test.txt
bye
pause
9 ответов
Разумно было бы хотеть создать сценарий FTP-сессии так, как представлял себе оригинальный постер, и именно с этим Expect может помочь. Пакетные файлы в Windows не могут этого сделать.
Но вместо того, чтобы делать cURL или Expect, вам может быть проще написать сценарий взаимодействия FTP с Powershell. Это другая модель, в которой вы не пишете текст напрямую для отправки на FTP-сервер. Вместо этого вы будете использовать Powershell для управления объектами, которые генерируют диалог FTP для вас.
Загрузить:
$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)
Скачать:
$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)
Вам нужен Powershell, чтобы сделать это. Если вы не знаете, Powershell - это оболочка типа cmd.exe, которая запускает ваши.bat-файлы. Но Powershell запускает файлы.ps1 и немного более мощный. Powershell - это бесплатное дополнение к Windows, которое будет встроено в будущие версии Windows. Получите это здесь.
Источник: http://poshcode.org/1134
Создайте командный файл с вашими командами
то есть: commands.txt
open www.domainhere.com
user useridhere
passwordhere
put test.txt
bye
Затем запустите FTP-клиент из командной строки: ftp -s:commands.txt
Примечание. Это будет работать для FTP-клиента Windows.
Изменить: Должен был быть разрыв строки после имени пользователя перед паролем.
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
Пакетные файлы не работают таким образом. Они не просто "набирают" все - они запускают системные команды, в этом случае ftp
дождитесь их возвращения и выполните следующую команду... так что в этом случае интерпретатор просто ждет ftp
выходить.
Если вы должны использовать ftp
команда, а затем подготовить файл сценария (например, commands.txt
и беги ftp -s:commands.txt
,
Но лучше использовать cURL или PHP/Perl/Python/ любой другой скрипт.
Я знаю, что это старый вопрос, но я хотел добавить кое-что к ответам, уже здесь, в надежде помочь кому-то еще.
Вы можете написать сценарий ftp
команда с -s:filename
вариант. Синтаксис - это просто список команд для передачи ftp
shell, каждый из которых заканчивается символом новой строки. На этой странице есть хорошая ссылка на команды, которые могут быть выполнены с ftp
,
Загрузить / скачать всю структуру каталогов
Используя нормальный ftp
не очень хорошо работает, когда вам нужно скопировать все дерево каталогов на или с FTP-сайта. Таким образом, вы можете использовать что-то вроде этого, чтобы справиться с этими ситуациями.
Эти скрипты работают с Windows ftp
Команда и позволяет загружать и скачивать целые каталоги из одной команды. Это делает его довольно самостоятельным при использовании в разных системах.
По сути, они отображают структуру каталогов, которая должна быть загружена / загружена, соответствующие дампы ftp
команды в файл, затем выполните эти команды, когда сопоставление завершится.
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
Этот сценарий генерирует командный файл, а затем передает командный файл в программу ftp, создавая журнал по пути. Наконец распечатайте оригинальный файл bat, командные файлы и журнал этого сеанса.
@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
У меня была похожая проблема - как оригинальный постер, я хотел автоматизировать загрузку файлов, но я не мог понять, как. Поскольку это находится на регистрационном терминале в магазине моей семьи, я не хотел устанавливать powershell (хотя это выглядит как простой вариант), просто хотел сделать простой файл.bat для этого. Это в значительной степени то, что сказал grawity и другой пользователь; Я новичок в этом, так что вот более подробный пример и объяснение (спасибо также http://www.howtogeek.com/howto/windows/how-to-automate-ftp-uploads-from-the-windows-command-line/ кто объясняет, как это сделать, используя только один файл.bat.)
По сути вам нужно 2 файла - один.bat и один.txt..Bat сообщает ftp.exe, какие переключатели использовать.. Txt предоставляет список команд для ftp.exe. В текстовом файле поместите это:
username
password
cd whereverYouWantToPutTheFile
lcd whereverTheFileComesFrom
put C:\InventoryExport\inventory.test (or your file path)
bye
Сохраните это где хотите. В файле BAT положить:
ftp.exe -s:C:\Windows\System32\test.txt destinationIP
pause
Очевидно, измените путь после -s: туда, где находится ваш текстовый файл. Уберите паузу, когда вы на самом деле ее запускаете - это просто, чтобы вы могли увидеть любые ошибки. Конечно, вы можете использовать команду "get" или любую другую команду ftp в файле.txt, чтобы делать все, что вам нужно.
Я не уверен, что вам нужна команда lcd в текстовом файле, как я сказал, что я новичок в использовании командной строки для такого типа вещей, но это работает для меня.
У меня была такая же проблема, и я решил ее с помощью решения, аналогичного тому, которое предоставил Cheeso, выше.
"не работает, говорит, что пароль необходим, пробовал пару разными способами"
Да, это потому, что сеансы FTP через командный файл не требуют, чтобы перед именем пользователя стояла строка "пользователь". Брось и попробуй.
Или, возможно, вы видите это, потому что ваш командный файл FTP не закодирован должным образом (это тоже меня немного). Это дерьмовая часть о генерации командного файла FTP во время выполнения. У внешнего командлета Powershell нет опции кодирования, которую будет принимать Windows FTP (по крайней мере, та, которую я не смог найти).
Независимо от того, как сделать WebClient.DownloadFile это путь.
Попробуйте вручную:
$ ftp www.domainhere.com
> useridhere
> passwordhere
> put test.txt
> bye
> pause