Назад | Перейти на главную страницу

PowerShell ftp get не сохраняет на Windows Server

С 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." }
}