Почему FtpWebRequest загружает файлы из корневого каталога? Может ли это вызвать ошибку 553?

Я создал сценарий PowerShell для загрузки файлов с FTP-сервера. Этот скрипт работает со всеми серверами, которые я тестировал, за исключением одного. Для этого одного сервера сценарий может подключиться, получить список каталогов, но каждый раз, когда он пытается загрузить файл, возвращается ошибка «553 File Unreachable». Ниже приведен код, который я использую для загрузки файлов.

function Get-FtpFile
{
    Param ([string]$fileUrl, $credentials, [string]$destination)
    try
    {
        $FTPRequest = [System.Net.FtpWebRequest]::Create($fileUrl)
        if ($credentials) 
        {
            $FTPRequest.Credentials = $credentials
        }
        $FTPRequest.Method = [System.Net.WebRequestMethods+Ftp]::DownloadFile
        $FTPRequest.UseBinary = $true
        $FTPRequest.UsePassive = $true

        # Send the ftp request
        $FTPResponse = $FTPRequest.GetResponse()

        # Get a download stream from the server response
        $ResponseStream = $FTPResponse.GetResponseStream()

        # Create the target file on the local system and the download buffer
        $LocalFile = New-Object IO.FileStream ($destination,[IO.FileMode]::Create)
        [byte[]]$ReadBuffer = New-Object byte[] 1024

        # Loop through the download
        do {
            $ReadLength = $ResponseStream.Read($ReadBuffer,0,1024)
            $LocalFile.Write($ReadBuffer,0,$ReadLength)
        }
        while ($ReadLength -ne 0)

        $ResponseStream.Close()
        $ReadBuffer.clear()
        $LocalFile.Close()
        $FTPResponse.Close()
    }
    catch [Net.WebException]
    {
        return "Unable to download because: $($_.exception)"
    }
}

Я также реализовал трассировку .NET для устранения этой проблемы. Ниже приведен один из блоков сообщений, полученных при попытке загрузить файл.

System.Net Information: 0 : [7712] FtpWebRequest#33194379::.ctor(ftp://**.**.**.**//record/5DE7D3810004)
System.Net Information: 0 : [7712] FtpWebRequest#33194379::GetResponse(Method=RETR.)
System.Net Information: 0 : [7712] FtpControlStream#18792280 - Created connection from 666.66.66.66:61255 to **.**.**.**:21.
System.Net Information: 0 : [7712] Associating FtpWebRequest#33194379 with FtpControlStream#18792280
System.Net Information: 0 : [7712] FtpControlStream#18792280 - Received response [220 FTP server ready. Username and password required]
System.Net Information: 0 : [7712] FtpControlStream#18792280 - Sending command [USER change]
System.Net Information: 0 : [7712] FtpControlStream#18792280 - Received response [331 Password required.]
System.Net Information: 0 : [7712] FtpControlStream#18792280 - Sending command [PASS ********]
System.Net Information: 0 : [7712] FtpControlStream#18792280 - Received response [230 Login successful. .]
System.Net Information: 0 : [7712] FtpControlStream#18792280 - Sending command [OPTS utf8 on]
System.Net Information: 0 : [7712] FtpControlStream#18792280 - Received response [502 Command not implemented, superfluous at this site.]
System.Net Information: 0 : [7712] FtpControlStream#18792280 - Sending command [PWD]
System.Net Information: 0 : [7712] FtpControlStream#18792280 - Received response [257 "/usr/apt/tesla/config" is the current directory.]
System.Net Information: 0 : [7712] FtpControlStream#18792280 - Sending command [TYPE I]
System.Net Information: 0 : [7712] FtpControlStream#18792280 - Received response [200 Switching to Binary mode.]
System.Net Information: 0 : [7712] FtpControlStream#18792280 - Sending command [PASV]
System.Net Information: 0 : [7712] FtpControlStream#18792280 - Received response [227 Entering Passive Mode (10,40,0,92,254,143)]
System.Net Information: 0 : [7712] FtpControlStream#18792280 - Sending command [RETR /record/5DE7D3810004]
System.Net Information: 0 : [7712] FtpControlStream#18792280 - Received response [553 File unavailable.]
System.Net Information: 0 : [7712] FtpWebRequest#33194379::(Releasing FTP connection#18792280.)

Я заметил, что FtpWebRequest не переходит в каталог, из которого он загружает файл, а вместо этого загружает этот файл из корневого каталога сервера (или любого пути, установленного в качестве корневого каталога). Может быть, поэтому я сталкиваюсь с ошибкой 553? Если да, то можно ли как-нибудь записать на компакт-диск каталог, из которого вы хотите загрузить файлы?


person MRoth    schedule 08.04.2020    source источник


Ответы (1)


Хотя и редко, но некоторые FTP-серверы не могут обрабатывать абсолютные пути с помощью команды RETR. Нужно сначала CWD перейти в каталог, а затем использовать RETR только с именем файла. FtpWebRequest не поддерживает это. Вам придется использовать другую библиотеку FTP.


Вы спрашивали о моем WinSCP. В его библиотеке .NET нет явного указания "каталога изменения". запрос либо. Но он работает CWD в определенных ситуациях, так что вы можете заставить его делать то, что вам нужно. В частности, он делает CWD перед листингом каталога. Таким образом, вы можете сделать явный список исходного каталога самостоятельно:

$session.ListDirectory("/record")
$session.GetFileToDirectory("/record/5DE7D3810004", "C:\local\path")

Или, если вы все равно хотите загрузить все файлы, вы можете попросить об этом, и WinSCP выполнит листинг (и CWD) внутри себя.

$session.GetFilesToDirectory("/record/*", "C:\local\path")

Между прочим, скрипт WinSCP имеет явный cd команда, так что вместо нее можно использовать скриптинг, пока из PowerShell использовать не так удобно, как сборку.


Или используйте еще одну библиотеку. Например, FluentFTP имеет FtpClient.SetWorkingDirectory.

person Martin Prikryl    schedule 10.04.2020
comment
Спасибо, Мартин, я действительно ценю всю помощь. - person MRoth; 10.04.2020