为什么 FtpWebRequest 从根目录下载文件?这会导致 553 错误吗?
Why does FtpWebRequest download files from the root directory? Can this cause a 553 error?
我构建了一个 PowerShell 脚本,用于从 FTP 服务器下载文件。该脚本适用于我用 expect 测试过的所有服务器。对于这台服务器,脚本能够连接、获取目录列表,但每次它尝试下载文件时都会返回“553 文件不可用”错误。下面是我用来下载文件的代码。
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
不会 CD 到它正在从中下载文件的目录,而是从服务器根目录(或设置为根目录的任何路径)下载该文件。这可能是我遇到 553 错误的原因吗?如果可以,有没有CD到你要下载文件的目录?
虽然很少见,但确实有一些 FTP 服务器无法使用 RETR
命令处理绝对路径。必须首先 CWD
到目录,然后仅使用 RETR
和文件名。 FtpWebRequest
不支持。您将不得不使用另一个 FTP 库。
你问过 my WinSCP. Its .NET library 也没有明确的 "change directory" 请求。但在某些情况下它会 CWD
,所以你可以让它做你需要的。它特别是 CWD
在目录列表之前。所以要么你可以自己做一个源目录的显式列表:
$session.ListDirectory("/record")
$session.GetFileToDirectory("/record/5DE7D3810004", "C:\local\path")
或者如果您想下载所有文件,您可以提出要求,WinSCP 将在内部列出(和 CWD
一起)。
$session.GetFilesToDirectory("/record/*", "C:\local\path")
顺便说一句,WinSCP scripting has an explicit cd
command,因此您可以改用脚本,虽然从 PowerShell 使用程序集并不方便。
或者使用另一个库。例如 FluentFTP has FtpClient.SetWorkingDirectory
.
我构建了一个 PowerShell 脚本,用于从 FTP 服务器下载文件。该脚本适用于我用 expect 测试过的所有服务器。对于这台服务器,脚本能够连接、获取目录列表,但每次它尝试下载文件时都会返回“553 文件不可用”错误。下面是我用来下载文件的代码。
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
不会 CD 到它正在从中下载文件的目录,而是从服务器根目录(或设置为根目录的任何路径)下载该文件。这可能是我遇到 553 错误的原因吗?如果可以,有没有CD到你要下载文件的目录?
虽然很少见,但确实有一些 FTP 服务器无法使用 RETR
命令处理绝对路径。必须首先 CWD
到目录,然后仅使用 RETR
和文件名。 FtpWebRequest
不支持。您将不得不使用另一个 FTP 库。
你问过 my WinSCP. Its .NET library 也没有明确的 "change directory" 请求。但在某些情况下它会 CWD
,所以你可以让它做你需要的。它特别是 CWD
在目录列表之前。所以要么你可以自己做一个源目录的显式列表:
$session.ListDirectory("/record")
$session.GetFileToDirectory("/record/5DE7D3810004", "C:\local\path")
或者如果您想下载所有文件,您可以提出要求,WinSCP 将在内部列出(和 CWD
一起)。
$session.GetFilesToDirectory("/record/*", "C:\local\path")
顺便说一句,WinSCP scripting has an explicit cd
command,因此您可以改用脚本,虽然从 PowerShell 使用程序集并不方便。
或者使用另一个库。例如 FluentFTP has FtpClient.SetWorkingDirectory
.