我有一个测试C#控制台应用程序,它使用FtpWebRequest
将文件传输到公共FTP服务器。
该应用程序可在我的Dev PC上运行,并且UsePassive设置为False。但是,当我将应用程序复制到Azure VM时,会引发以下异常:
远程服务器返回错误:(500)语法错误,命令 无法识别。
因此,总而言之,以下是在本地和Azure上运行应用程序时的结果:
UsePassive Local PC Azure VM
---------- -------- --------
True ok ok
False ok ERROR!
为System.Net
启用跟踪将显示以下内容(摘录):
System.Net Information: 0 : [5716] FtpControlStream#60068066 - Created connection from 10.0.0.4:49706 to 90.130.70.73:21.
System.Net Information: 0 : [5716] Associating FtpWebRequest#45004109 with FtpControlStream#60068066
System.Net Information: 0 : [5716] FtpControlStream#60068066 - Received response [220 (vsFTPd 2.3.5)]
System.Net Information: 0 : [5716] FtpControlStream#60068066 - Sending command [USER anonymous]
System.Net Information: 0 : [5716] FtpControlStream#60068066 - Received response [331 Please specify the password.]
System.Net Information: 0 : [5716] FtpControlStream#60068066 - Sending command [PASS ********]
System.Net Information: 0 : [5716] FtpControlStream#60068066 - Received response [230 Login successful.]
System.Net Information: 0 : [5716] FtpControlStream#60068066 - Sending command [OPTS utf8 on]
System.Net Information: 0 : [5716] FtpControlStream#60068066 - Received response [200 Always in UTF8 mode.]
System.Net Information: 0 : [5716] FtpControlStream#60068066 - Sending command [PWD]
System.Net Information: 0 : [5716] FtpControlStream#60068066 - Received response [257 "/"]
System.Net Information: 0 : [5716] FtpControlStream#60068066 - Sending command [TYPE I]
System.Net Information: 0 : [5716] FtpControlStream#60068066 - Received response [200 Switching to Binary mode.]
System.Net Information: 0 : [5716] FtpControlStream#60068066 - Sending command [PORT 10,0,0,4,194,43]
System.Net Information: 0 : [5716] FtpControlStream#60068066 - Received response [500 Illegal PORT command.]
System.Net Information: 0 : [5716] FtpWebRequest#45004109::(Releasing FTP connection#60068066.)
System.Net Error: 0 : [5716] Exception in FtpWebRequest#45004109::GetRequestStream - The remote server returned an error: (500) Syntax error, command unrecognized..
at System.Net.FtpWebRequest.SyncRequestCallback(Object obj)
这是我的应用程序的源代码:
var fileContents = Encoding.UTF8.GetBytes("this is a test");
Console.Write("UsePassive? (y/n)");
var passive = Console.ReadKey();
var usePassive = passive.Key == ConsoleKey.Y;
var request = (FtpWebRequest)WebRequest.Create("ftp://speedtest.tele2.net/upload/mytest.txt");
request.Credentials = new NetworkCredential("anonymous", "anonymous");
request.Method = WebRequestMethods.Ftp.UploadFile;
request.UsePassive = usePassive;
request.ContentLength = fileContents.Length;
using (var requestStream = request.GetRequestStream())
{
requestStream.WriteAsync(fileContents, 0, fileContents.Length);
}
using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
{
Console.WriteLine($"Upload File Complete, status {response.StatusDescription}");
}
Azure VM不属于网络安全组。我曾尝试在VM上禁用防火墙,但该应用仍然会引发异常。
我该如何解决?我的应用要求将UsePassive
设置为False
。
答案 0 :(得分:1)
PORT 10,0,0,4,194,43
500 Illegal PORT command.
10.0.0.4是专用IP地址。您无法将专用IP地址发送到FTP服务器,因为它无法重新连接到它(因此出现500错误)。您必须使用您的公共IP地址。我不知道如何为FtpWebRequest
覆盖本地IP地址。在我看来,检查.NET源代码实际上是不可能的。
正如我已经写过的那样:甚至不要尝试使用活动模式。从网络角度来看,设置很复杂。请参阅我在Network configuration for FTP active and passive modes上的文章。
同样,使用被动模式。我知道您在被动模式下也遇到问题。但是它们比主动模式的问题更有可能解决。
如果您坚持使用活动模式,请使用支持指定本地IP地址的FTP客户端库。
例如使用WinSCP .NET assembly:
// Set up session options
SessionOptions sessionOptions = new SessionOptions
{
Protocol = Protocol.Ftp,
HostName = "10.0.0.4",
FtpMode = FtpMode.Active,
};
using (Session session = new Session())
{
session.AddRawConfiguration(@"Interface\ExternalIpAddress", "your public IP address");
// Connect
session.Open(sessionOptions);
// Upload
session.PutFiles(@"C:\local\path\file.txt", "/upload/mytest.txt").Check();
}
(我是WinSCP的作者)
您仍然必须为所有数据连接端口打开VM防火墙。
虽然我没有对其进行测试,但看起来如果本地计算机(VM)仅具有IPv6 IP地址,FtpWebRequest
将使用EPRT
命令不地址,而不是带有IP地址的PORT
命令。什么也可以解决您的问题。您仍然必须为所有数据连接端口打开VM防火墙。