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

标签 c# .net vb.net ftp ftpwebrequest

更新(此问题的原因):

好吧,我设法 -在@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 44.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

Wireshark results <code>.NET 4.5.2</code>

.NET 2.0

Wireshark results <code>.NET 2.0</code>

有什么想法吗?

旁注:虽然我的代码是在 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/

相关文章:

c# - 如何在 ASP NET 中通过公共(public) API 通过 HTTP 发布文件?

vb.net - Roslyn VB.NET 中缺少我的命名空间

ios - Obj-C 和 VB.Net 之间的加密兼容性

c# - 检查“在字符串 vb.net

c# - 如何读取和编辑 XML 节点

c# - 具有多个内容的 WPF 样式

c# - 如何从我的 mono for android 应用程序中获取网络文件列表?

C# Windows 窗体类型转换错误

c# - 是否可以限制 Parallel.ForEach 的内核数?

c# - 一个好的 C# 文件路径生成器库?