更新(此问题的原因):
好吧,我设法 -在@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, 0, 1024)
If bytesIn > 0 Then output.Write(buffer, 0, 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捕获请求和响应,我的假设是正确的,但是我仍然不明白问题到底是什么,因为我在两个 。.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);
}
}
抱歉 - 我现在不能尝试,所以这更像是一个建议......
编辑: 或者,您可以使用一些行为类似于 .NET 4 的 ftp 库。
关于c# - 从(特定)服务器下载 FTP 文件适用于 .NET 4+,但不适用于 .NET 2.0,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41858773/