c# – 从(特定)服务器下载FTP文件适用于.NET 4,但不适用于.NET 2.0

更新(此问题的原因):

好吧,我在@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捕获请求和响应,我的假设是正确的,但我仍然不明白问题究竟是什么,因为我’ m在两个.NET版本上使用相同的代码.

Wireshark结果

.NET 4.5.2

《c# – 从(特定)服务器下载FTP文件适用于.NET 4,但不适用于.NET 2.0》

.NET 2.0

《c# – 从(特定)服务器下载FTP文件适用于.NET 4,但不适用于.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.

点赞