[英]Download FTP file from a (specific) server works on .NET 4+, but doesn't work on .NET 2.0
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的评论的帮助下设法找出问题的确切位置,并且我正在努力寻找解决方案。
CWD
(change working directory). CWD
(更改工作目录)。 .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). .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
。
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 4
或4.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
版本上使用相同的代码 。
.NET 4.5.2
.NET 2.0
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.