6

我正在尝试使以下代码正常工作:

  string url = String.Format(@"SOMEURL");
  string user = "SOMEUSER";
  string password = "SOMEPASSWORD";

  FtpWebRequest ftpclientRequest = (FtpWebRequest)WebRequest.Create(new Uri(url));
  ftpclientRequest.Method = WebRequestMethods.Ftp.ListDirectory;
  ftpclientRequest.UsePassive = true; 
  ftpclientRequest.Proxy = null;
  ftpclientRequest.Credentials = new NetworkCredential(user, password);
  FtpWebResponse response = ftpclientRequest.GetResponse() as FtpWebResponse;

这通常有效,但对于 1 个特定服务器,这会给出错误 500:无法识别语法。更改目录命令在问题服务器上被禁用,站点管理员告诉我,.NET 默认情况下对所有 FTP 连接发出更改目录命令。真的吗?有没有办法禁用它?
编辑:当我从命令行登录时,我在正确的目录中:
ftp> pwd
257 "/" is current directory

4

5 回答 5

11

我刚刚在我们的一个开发服务器上对此进行了测试,确实有一个由 .NET FtpWebRequest 发出的 CWD:

从 172.16.3.210 到 172.16.3.210:21 的新连接(显式 SSL)
主机名解析:devpc
发送欢迎信息。
220 Gene6 FTP Server v3.10.0 (Build 2) 就绪...
用户测试用户
testuser, 331 testuser 需要密码。
测试用户,通过 ****
testuser,以“testuser”身份登录。
testuser, 230 用户 testuser 已登录。
testuser, OPTS utf8 on
testuser, 501 请先CLNT。
测试用户,残疾人
testuser, 257 "/" 是当前目录。
测试用户,CWD /
testuser,更改目录 '/' -> 'D:\testfolder' -> 允许访问。
testuser, 250 CWD 命令成功。“/”是当前目录。
测试用户,类型 I
testuser, 200 类型设置为 I。
测试用户,端口 172,16,3,210,4,127
testuser, 200 端口命令成功。
测试用户,NLST
testuser, 150 打开目录列表的数据连接。
testuser, 226 传输正常。
testuser, 421 连接关闭,超时。
测试用户,断开连接。(00d00:05:01)

在创建 FtpWebRequest 对象时,甚至没有在 uri 中指定“/”。

如果您调试或浏览源代码,一个名为“FtpControlStream”的类就会发挥作用。查看调用堆栈:

System.dll!System.Net.FtpControlStream.BuildCommandsList(System.Net.WebRequest req) 第 555 行 C#
System.dll!System.Net.CommandStream.SubmitRequest(System.Net.WebRequest 请求 =
    {System.Net.FtpWebRequest}, bool async = false, bool readInitalResponseOnConnect = true) 第 143 行 C#
System.dll!System.Net.FtpWebRequest.TimedSubmitRequestHelper(bool async) 第 1122 行 + 0x13 字节 C#
System.dll!System.Net.FtpWebRequest.SubmitRequest(bool async = false) 第 1042 行 + 0xc 字节 C#
System.dll!System.Net.FtpWebRequest.GetResponse() 第 649 行 C#

有一个名为 BuildCommandsList() 的方法被调用。BuildCommandsList() 构建要发送到 FTP 服务器的命令列表。此方法具有以下代码片段:

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)); 
}

在第一次连接到服务器时,m_PreviousServerPath 始终为 null,newServerPath 的值为“/”,并由名为 GetPathAndFileName() 的函数计算(在此代码块之前的几行调用)。GetPathAndFileName() 如果没有提供路径或者如果在 'ftp://....' uri 的末尾明确添加了“/”,则将 newServerPath 计算为“/”。

所以这当然最终会导致 CWD 命令被添加到命令管道中,因为 null != "/"。

简而言之,不幸的是,您无法覆盖此行为,因为它已在源代码中被烧毁。

于 2008-10-14T16:17:25.810 回答
1

虽然这个帖子是很久以前的......没关系,我会在这里提供答案。

不要ftp://server/path用作 uri,而是尝试ftp://server/%2fpath/.

添加的%2f" 只是一个转义的/,添加这将使 C# 将整个路径视为绝对路径。否则 C# 将ftp://server/使用用户名登录,转到用户的主文件夹,然后 cd 到您指定的路径,因此您的路径变为user_home_path/path,可能不可取。

更多信息可以在 msdn http://msdn.microsoft.com/en-us/library/system.net.ftpwebrequest.aspx找到

希望这可以帮助。

于 2011-11-17T10:23:18.250 回答
0

我想我们不久前也遇到过类似的问题,但我不记得确切的细节了。

要防止 .net 发出 cd 命令,请查看是否将您登录的用户的默认目录设置为您要工作的目录。您可以使用命令行 ftp 客户端来检查这一点。

于 2008-10-14T14:53:28.757 回答
0

这是一个解决方案:使用这个由 Dan 在 C-SharpCorner.com 制作的免费、开源、C# FTP 客户端库: http ://www.c-sharpcorner.com/uploadfile/danglass/ftpclient12062005053849am/ftpclient.aspx

以下是上传文件的一些示例代码:

FtpClient ftp = new FtpClient(FtpServer,FtpUserName,FtpPassword);
ftp.Login();
ftp.Upload(@"C:\image.jpg");
ftp.Close(); 

该库开箱即用,但也可以轻松扩展和修改。

于 2008-10-15T17:19:15.560 回答
0

使用上面的信息,这对我有用。

发送 CWD - ftpState.ftpRequest = GetRequest(" ftp://192.168.0.2/tmp/file2download ")

不发送 CWD - ftpState.ftpRequest = GetRequest(" ftp://192.168.0.2//tmp/file2download ") 注意服务器 IP(或名称)后面的 //

点网 2.0 版

Private Function GetRequest(ByVal URI As String) As FtpWebRequest
    'create request
    Dim result As FtpWebRequest = CType(FtpWebRequest.Create(URI), FtpWebRequest)
    Return result
End Function
于 2017-10-04T21:11:05.357 回答