简体   繁体   English

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

[英]Download FTP file from a (specific) server works on .NET 4+, but doesn't work on .NET 2.0

Update (the reason of this issue): 更新(此问题的原因):

Okay, I managed - with the help of @MitchelSellers's comment - to figure out where the problem exactly is, and I'm trying to find a solution for it. 好吧,我在@MitchelSellers的评论的帮助下设法找出问题的确切位置,并且我正在努力寻找解决方案。

  • Obviously this server doesn't allow the command CWD (change working directory). 显然这个服务器不允许命令CWD (更改工作目录)。
  • Now downloading a file using .NET 2.0 -for unknown reasons- it sends this command followed by / after logging in, to change the working directory to the current working directory!! 现在,使用下载文件.NET 2.0 -对于未知reasons-发送此命令后面/登录,改变工作目录到当前工作目录 (as shown below, and I also confirmed that using FileZilla with another server). (如下图所示,我也确认使用FileZilla与另一台服务器)。
  • Also as shown below, that's not the case with the recent versions of .NET , which is why it works on .NET 4.x . 同样如下所示,最新版本的.NET不是这种情况,这就是它适用于.NET 4.x

So, I'm trying to find a way to make it work on .NET 2.0 . 所以,我正试图找到一种方法使它在.NET 2.0


The original question: 原来的问题:

Here's my code: 这是我的代码:

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

When running that code on .NET 4 or 4.x , it works perfectly fine. .NET 44.x上运行该代码时,它可以正常工作。 However when running it on .NET 2.0 (I have to use .NET 2.0) , it throws an exception when calling request.GetResponse . 但是,当在.NET 2.0上运行它(我必须使用.NET 2.0)时 ,它会在调用request.GetResponse时抛出异常。 Here's the exception message is: 这是异常消息:

The remote server returned an error: (501) Syntax error in parameters or arguments. 远程服务器返回错误:(501)参数或参数中的语法错误。

I figured out that there must be something wrong with the request sent from .NET 2.0 , so I decided to capture requests and responses using Wireshark, and my assumption was correct 我发现从.NET 2.0发送的请求肯定有问题,所以我决定使用Wireshark捕获请求和响应,我的假设是正确的 , but I still don't understand what the problem exactly is since I'm using the same code on both .NET versions ,但我仍然不明白究竟是什么问题,因为我在两个.NET版本上使用相同的代码 .

Wireshark results Wireshark结果

.NET 4.5.2

Wireshark结果<code> .NET 4.5.2 </ code>

.NET 2.0

Wireshark结果<code> .NET 2.0 </ code>

Any ideas? 有任何想法吗?

Side note: Although my code is in VB, any answer with C# code is welcomed. 旁注:尽管我的代码是在VB中,但欢迎使用C#代码的任何答案。

UPDATE according to comment: 根据评论更新:

.NET 2 does not honour that flag :-( It contains a method called BuildCommandsList() - part the source in .NET 2 looks like this: .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)); 
}

So basically the CWD is hardcoded in .NET 2. This leaves you with 2 undesirable "options": either make the FTP server RFC compliant (which it currently is not!) or user some other library/way to access it. 所以基本上CWD在.NET 2中是硬编码的。这给你留下了2个不受欢迎的“选项”:要么使FTP服务器符合RFC(目前它不是!),要么用户其他一些库/方式来访问它。

A very unusual way might be to call/automate the DOS-command ftp from your .NET application... 一种非常不寻常的方式可能是从.NET应用程序调用/自动化DOS命令ftp ...

Left for reference: 留待参考:

MS has documented this change of behaviour between .NET 2 and .NET 4 here: https://support.microsoft.com/en-au/help/2134299/system.net.ftpwebrequest-class-behaves-differently-in-.net-framework-4-vs-.net-framework-3.5 MS在此处记录了.NET 2和.NET 4之间的这种行为变化: https//support.microsoft.com/en-au/help/2134299/system.net.ftpwebrequest-class-behaves-differently-in-。净框架-4- VS-.NET框架-3.5

I suspect that it is worth a try to remove the described flag in .NET 2.0 - something similar to this: 我怀疑在.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);
        }
}

Sorry - I can't try this right now so this more like a suggestion... 对不起 - 我现在不能尝试这个,所以这更像是一个建议......

EDIT: Alternatively you could use some ftp library which behaves similar to what .NET 4 does. 编辑:或者你可以使用一些ftp库,其行为类似于.NET 4。

Have you tried making the filePath an absolute path? 您是否尝试过将filePath设为绝对路径? ie

Dim filePath As String = "ftp://ftp.kohlandfrisch.com/%2ftestfile"

%2f represents the / character. %2f表示/字符。

This might be a workaround. 这可能是一种解决方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在 C#/.NET 中向/从 FTP 服务器上传和下载文件 - Upload and download a file to/from FTP server in C#/.NET 使用 WinSCP .NET 程序集从 FTP 服务器下载除特定文件夹之外的所有文件 - Download all files except a specific folder from FTP server using WinSCP .NET assembly .net core Ftp 命令不起作用并且在我的生产服务器上没有引发任何错误 - .net core Ftp commands doesn't work and raises no error on my production server 如何通过 .net 控制台应用程序从 ftp 服务器下载名称中包含希伯来语字符的文件? - How can I download a file with Hebrew characters in its name from an ftp server via .net console application? 为什么带有lambda表达式的代码在.NET Framework 2.0中不起作用? - Why doesn't this code with a lambda expression work in .NET Framework 2.0? 使用 .NET 2.0,我如何将 FTP 到服务器,获取文件,并删除文件? - Using .NET 2.0, how do I FTP to a server, get a file, and delete the file? 从服务器下载 ASP.NET 文件 - ASP.NET file download from server 从服务器asp.net下载文件 - download file from server asp.net 为什么asp.net下载不起作用? - Why doesn't asp.net download work? 如何从.net MVC将文件上传到Azure中的ftp服务器? - How to upload a file to ftp server in azure from .net MVC?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM