C# FtpWebRequest 失败并在成功时抛出异常

问题描述

标题似乎自相矛盾?继续阅读...

我正在尝试使用 FtpWebRequest 在 FTP 服务器上列出文件夹。

当我列出单个文件夹“myserver.whatever.com/folder”时,它成功了。

当我列出嵌套文件夹时,“myserver.whatever.com/folder/folder1”失败。除非它抛出一个异常,告诉我它成功了。

具体来说,这段代码

request = (FtpWebRequest)WebRequest.Create(m_server + folder);
request.ClientCertificates = m_certificates;
request.Credentials = new NetworkCredential(m_userName.normalize(),password.normalize() );
request.EnableSsl = true;
request.Method = WebRequestMethods.Ftp.ListDirectory;
response = (FtpWebResponse)request.GetResponse();
Stream responseStream = response.GetResponseStream();
StreamReader reader = new StreamReader(responseStream);

抛出这个异常:

The Remote Server returned an error: 150 opening data connection. List started\r\n

微软不知道 150 不是一个错误吗?微软的缺陷有什么解决方法吗?

根据其他帖子,我已经尝试删除并重新安装一些 KB,但无济于事。

如果有办法用这个 FtpWebRequest 对象发出“chdir”,我可能会解决这个问题。但是我找不到任何东西。

这似乎不是访问权限问题。否则服务器应该返回 550。

有一些关于数据端口会话恢复的帖子,但是,由于这不会在一个文件夹级别上失败,只有在两个文件夹级别上失败,因此数据连接似乎不是问题。

大家有什么建议吗?

解决方法

我发现了问题所在。这可能不是一个完整的解决方案,但它是一种解决方法。

首先,感谢 MartinPrikryl 将我引导至日志。一段日志看起来像这样:

System.Net Information: 0 : [24980] InitializeSecurityContext(In-Buffer length=0,Out-Buffer length=188,returned code=ContinueNeeded).
System.Net Information: 0 : [24980] FtpWebRequest#8810861::(Releasing FTP connection#49582139.)
System.Net Error: 0 : [24980] Exception in FtpWebRequest#8810861::GetResponse - The remote server returned an error: 150 Opening data connection. List started
..
   at System.Net.FtpWebRequest.SyncRequestCallback(Object obj)
   at System.Net.CommandStream.Dispose(Boolean disposing)
   at System.IO.Stream.Close()
   at System.Net.ConnectionPool.Destroy(PooledStream pooledStream)
   at System.Net.ConnectionPool.PutConnection(PooledStream pooledStream,Object owningObject,Int32 creationTimeout,Boolean canReuse)
   at System.Net.FtpWebRequest.FinishRequestStage(RequestStage stage)
   at System.Net.FtpWebRequest.GetResponse()

因此,这似乎来自服务器提前关闭的数据连接。我不知道这个服务器是什么,也不知道它是什么风格的 *NIX。

我的解决方案是简单地改变

request.Method = WebRequestMethods.Ftp.ListDirectory;

request.Method = WebRequestMethods.Ftp.ListDirectoryDetails;

这将导致必须手动解析的 Unix 样式列表。在这种空目录的情况下,它只是:

dr-xr-xr-x   0 --NA--   --NA--            2 Dec 18 15:48 .
dr-xr-xr-x   0 --NA--   --NA--           16 Dec 18 15:48 ..

所以,有东西要读,数据通道不会过早关闭。

这与 Windows 风格的目录列表不同,后者是(显然不是空列表)

12-28-20  06:45PM       <DIR>          Some_Folder
10-07-20  09:35AM                 1148 a_file

因此,当使用“ListDirectoryDe​​tails”时,需要确定提供回复的服务器类型,这是一项非常简单的任务。

注意:

我在本地 Ubuntu 机器上重复了测试,没有遇到客户服务器给我的这个问题。所以我不清楚 vsftpd 和他们的服务器之间有什么区别,它不识别自己(显然是出于安全原因)。