好吧,我在@MitchelSellers的评论的帮助下进行了管理 – 找出问题的确切位置,并且我正在努力寻找解决方案.
>显然这个服务器不允许命令CWD(更改工作目录).
>现在使用.NET 2.0下载文件 – 由于未知原因 – 它会在登录后发送此命令,然后将该工作目录更改为当前工作目录! (如下图所示,我也确认使用FileZilla与另一台服务器).
>同样如下所示,最新版本的.NET不是这种情况,这就是它适用于.NET 4.x的原因.
所以,我正试图找到一种方法使它在.NET 2.0上运行.
原来的问题:
这是我的代码:
Private Sub DownloadTestFile() Dim filePath As String = "ftp://ftp.kohlandfrisch.com/testfile" Dim request As FtpWebRequest Dim buffer(1023) As Byte Dim bytesIn As Integer request = DirectCast(WebRequest.Create(filePath),FtpWebRequest) request.Method = WebRequestMethods.Ftp.DownloadFile request.Credentials = New NetworkCredential("username","password") request.UseBinary = False request.UsePassive = True request.Proxy = Nothing Using stream As IO.Stream = request.GetResponse.GetResponseStream Using output = IO.File.Create(localFilePath) bytesIn = 1 Do Until bytesIn < 1 bytesIn = stream.Read(buffer,1024) If bytesIn > 0 Then output.Write(buffer,bytesIn) Loop End Using End Using End Sub
在.NET 4或4.x上运行该代码时,它可以正常工作.但是,当在.NET 2.0上运行它(我必须使用.NET 2.0)时,它会在调用request.GetResponse时抛出异常.这是异常消息:
The remote server returned an error: (501) Syntax error in parameters
or arguments.
我发现从.NET 2.0发出的请求肯定有问题,所以我决定使用Wireshark捕获请求和响应,我的假设是正确的,但我仍然不明白问题究竟是什么,因为我’ m在两个.NET版本上使用相同的代码.
Wireshark结果
.NET 4.5.2
.NET 2.0
有任何想法吗?
旁注:尽管我的代码是在VB中,但欢迎使用C#代码的任何答案.
解决方法
.NET 2不尊重该标志:-(
它包含一个名为BuildCommandsList()的方法 – 部分.NET 2中的源代码如下所示:
if (m_PreviousServerPath != newServerPath) { if (!m_IsRootPath && m_LoginState == FtpLoginState.LoggedIn && m_LoginDirectory != null) { newServerPath = m_LoginDirectory+newServerPath; } m_NewServerPath = newServerPath; commandList.Add(new PipelineEntry(FormatFtpCommand("CWD",newServerPath),PipelineEntryFlags.UserCommand)); }
所以基本上CWD在.NET 2中是硬编码的.
这将为您留下2个不受欢迎的“选项”:要么使FTP服务器符合RFC(当前不是!),要么使用其他一些库/方式来访问它.
一种非常不寻常的方式可能是从.NET应用程序调用/自动化DOS命令ftp …
留待参考:
MS在此记录了.NET 2和.NET 4之间的这种行为变化:https://support.microsoft.com/en-au/help/2134299/system.net.ftpwebrequest-class-behaves-differently-in-.net-framework-4-vs-.net-framework-3.5
我怀疑在.NET 2.0中删除描述的标志值得尝试 – 类似于:
private static void SetMethodRequiresCWD() { Type requestType = typeof(FtpWebRequest); FieldInfo methodInfoField = requestType.GetField("m_MethodInfo",BindingFlags.NonPublic | BindingFlags.Instance); Type methodInfoType = methodInfoField.FieldType; FieldInfo knownMethodsField = methodInfoType.GetField("KnownMethodInfo",BindingFlags.Static | BindingFlags.NonPublic); Array knownMethodsArray = (Array)knownMethodsField.GetValue(null); FieldInfo flagsField = methodInfoType.GetField("Flags",BindingFlags.NonPublic | BindingFlags.Instance); int MustChangeWorkingDirectoryToPath = 0x100; foreach (object knownMethod in knownMethodsArray) { int flags = (int)flagsField.GetValue(knownMethod); flags &= (~MustChangeWorkingDirectoryToPath); flagsField.SetValue(knownMethod,flags); } }
对不起 – 我现在不能尝试这个,所以这更像是一个建议……
编辑:或者你可以使用一些ftp库,它的行为类似于.NET 4.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。