好的,我在@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
时抛出异常。这里的例外信息是:
远程服务器返回错误:(501)参数中的语法错误 或论据。
我发现从.NET 2.0
发送的请求肯定有问题,所以我决定使用Wireshark捕获请求和响应,我的假设是正确的,但我仍然没有&#39;因为我在上使用相同的代码,所以我明白了问题究竟是什么。.NET
个版本
.NET 4.5.2
.NET 2.0
有什么想法吗?
旁注:虽然我的代码是在VB中,但欢迎使用C#代码的任何答案。
答案 0 :(得分:1)
根据评论更新:
.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个不受欢迎的&#34;选项&#34;:要么使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。
答案 1 :(得分:0)
您是否尝试过将filePath设为绝对路径?即
Dim filePath As String = "ftp://ftp.kohlandfrisch.com/%2ftestfile"
%2f 代表 / 字符。
这可能是一种解决方法。