С Windows Server 2012, используя PoweShell
, Я подключаюсь к удаленному устройству через ftp
и беги get
для получения файла. Процесс проходит без проблем, но файл не сохраняется на моем локальном компьютере. Команда возвращает Operation Complete
и через несколько секунд соединение закрывается.
Operation CompleteConnection closed by remote host.
ftp>
В месте назначения временный файл размера 0
создается в начале процесса и остается неизменным. Tmp6A94.tmp
Я попытался открыть брандмауэр после этого Как настроить брандмауэр Windows для FTP-сервера в пассивном режиме
netsh advfirewall firewall add rule name=”FTP Service” dir=in protocol=TCP enable=yes action=allow profile=any service=ftpsvc localport=any
netsh advfirewall set global StatefulFTP disable
Что мне не хватает?
ИЗМЕНИТЬ 1
Я протестировал ftp
поведение на другом WS2012, а также на WS2012R2, и у них нет такой же проблемы. Ни у одного из них нет пассивного режима ftp межсетевого экрана. Интересно, может ли быть какое-то другое правило брандмауэра, разрешающее передачу по ftp.
РЕДАКТИРОВАТЬ 2
Это PowerShell
скрипт, который я использую для получения файла с удаленного устройства через ftp
:
function getFTPFile([String]$fileName)
{
$ftpUser = "user"
$ftpPassword = "password"
$ftpServer = "ftpServer"
$webclient = New-Object System.Net.WebClient
$webclient.Credentials = New-Object System.Net.NetworkCredential($ftpUser, $ftpPassword)
$uri = New-Object System.Uri("$ftpServer/files")
$webclient.DownloadFile($uri, $fileName)
}
Запуск этого сценария или выполнение его вручную из PowerShell
консоль дает тот же результат. Все будет работать правильно, пока файл не нужно будет сохранить в месте назначения. Я успешно использовал этот сценарий на других серверах Windows.
Это ошибка, вызванная сценарием:
Exception calling "DownloadFile" with "2" argument(s): "The remote server returned an error: 150-Starting operation:
STATUS: Getting logs ...
Please wait...
Please wait...
STATUS: Finished getting logs
STATUS: get logs operation is complete
Size: 8262246 bytes
Please wait for 8 seconds ...
Operation Complete150-Accepted data connection
150 (8262246 bytes) to download
."
At C:\Users\administrator\getFTPFile.ps1:73 char:2
+ $webclient.DownloadFile($uri, $fileName)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : WebException
А это неудачная операция из PowerShell
Подсказка:
ftp> get logs logsFile
200 PORT command successful
150-Starting operation:
STATUS: Getting logs ...
Please wait...
Please wait...
STATUS: Finished getting logs
STATUS: get logs operation is complete
Size: 8283146 bytes
Please wait for 8 seconds ...
Operation CompleteConnection closed by remote host.
Это результат успешной передачи:
ftp> get logs logsFile
200 PORT command successful
150-Starting operation:
STATUS: Getting logs ...
Please wait...
Please wait...
STATUS: Finished getting logs
STATUS: get logs operation is complete
Size: 8283146 bytes
Please wait for 8 seconds ...
Operation Complete150-Connecting to port 63596
150 (8275012 bytes) to download
226-File successfully transferred
226 0.778 seconds (measured here), 10.15 Mbytes per second
ftp: 8275012 bytes received in 0.76Seconds 10916.90Kbytes/sec.
Кроме того, я не пробовал никаких других FTP-клиентов.
РЕДАКТИРОВАТЬ 3
Теперь работает при использовании ftp
из PowerShell
терминал и не работает через скрипт, запустил из PowerShell
.
Я не уверен, каков именно процесс WebClient::DownloadFile
метод, но мне кажется, что он прерывает ftp-соединение прямо перед завершением передачи загрузки, что приводит к сбою операции.
Используя асинхронный метод, мне удалось успешно загрузить файл.
Вот моя обновленная функция с использованием WebClient::DownloadFileTaskAsync
метод. Я также реализовал проверку статуса.
function getFTPfile([String]$fileName)
{
$ftpUser = "user"
$ftpPassword = "password"
$ftpServer = "ftpServer"
$webclient = New-Object System.Net.WebClient
$webclient.Credentials = New-Object System.Net.NetworkCredential($ftpUser, $ftpPassword)
$uri = New-Object System.Uri("$ftpServer/files")
$job = $webclient.DownloadFileTaskAsync($uri, $fileName)
while(!$job.IsCompleted)
{
Write-Host "Downloading file..."
sleep 10
}
if($job.Status -ne "RanToCompletion")
{ Write-Host "Failed to download file." }
else
{ Write-Host "Download successful." }
}