How to send arbitrary FTP commands in C#

后端 未结 4 1039
隐瞒了意图╮
隐瞒了意图╮ 2020-12-03 15:46

I have implemented the ability to upload, download, delete, etc. using the FtpWebRequest class in C#. That is fairly straight forward.

What I need to d

相关标签:
4条回答
  • 2020-12-03 16:15

    I don't think it can be done with FtpWebRequest... The only way to specify a FTP command is through the Method property, and the documentation states :

    Note that the strings defined in the WebRequestMethods.Ftp class are the only supported options for the Method property. Setting the Method property to any other value will result in an ArgumentException exception.

    SITE and SYST are not among the predefined options, so I guess you're stuck...

    Don't waste time to try the WebClient class, it will give you even less flexibility than FtpWebRequest.

    However, there are plenty of third-party FTP implementation, open source or commercial, and I'm pretty sure some of them can handle custom commands...

    0 讨论(0)
  • 2020-12-03 16:22

    The FtpWebRequest won't help you as Thomas Levesque has said in his answer. You can use some third party solutions or the following, simplified TcpClient based code which I have refactored from an answer written in Visual Basic:

    public static void SendFtpCommand()
    {
        var serverName = "[FTP_SERVER_NAME]";
        var port = 21;
        var userName = "[FTP_USER_NAME]";
        var password = "[FTP_PASSWORD]"
        var command = "SITE CHMOD 755 [FTP_FILE_PATH]";
    
        var tcpClient = new TcpClient();
        try
        {
            tcpClient.Connect(serverName, port);
            Flush(tcpClient);
    
            var response = TransmitCommand(tcpClient, "user " + userName);
            if (response.IndexOf("331", StringComparison.OrdinalIgnoreCase) < 0)
                throw new Exception(string.Format("Error \"{0}\" while sending user name \"{1}\".", response, userName));
    
            response = TransmitCommand(tcpClient, "pass " + password);
            if (response.IndexOf("230", StringComparison.OrdinalIgnoreCase) < 0)
                throw new Exception(string.Format("Error \"{0}\" while sending password.", response));
    
            response = TransmitCommand(tcpClient, command);
            if (response.IndexOf("200", StringComparison.OrdinalIgnoreCase) < 0)
                throw new Exception(string.Format("Error \"{0}\" while sending command \"{1}\".", response, command));
        }
        finally
        {
            if (tcpClient.Connected)
                tcpClient.Close();
        }
    }
    
    private static string TransmitCommand(TcpClient tcpClient, string cmd)
    {
        var networkStream = tcpClient.GetStream();
        if (!networkStream.CanWrite || !networkStream.CanRead)
            return string.Empty;
    
        var sendBytes = Encoding.ASCII.GetBytes(cmd + "\r\n");
        networkStream.Write(sendBytes, 0, sendBytes.Length);
    
        var streamReader = new StreamReader(networkStream);
        return streamReader.ReadLine();
    }
    
    private static string Flush(TcpClient tcpClient)
    {
        try
        {
            var networkStream = tcpClient.GetStream();
            if (!networkStream.CanWrite || !networkStream.CanRead)
                return string.Empty;
    
            var receiveBytes = new byte[tcpClient.ReceiveBufferSize];
            networkStream.ReadTimeout = 10000;
            networkStream.Read(receiveBytes, 0, tcpClient.ReceiveBufferSize);
    
            return Encoding.ASCII.GetString(receiveBytes);
        }
        catch
        {
            // Ignore all irrelevant exceptions
        }
    
        return string.Empty;
    }
    

    You can expect the following flow while getting through the FTP:

    220 (vsFTPd 2.2.2)
    user [FTP_USER_NAME]
    331 Please specify the password.
    pass [FTP_PASSWORD]
    230 Login successful.
    SITE CHMOD 755 [FTP_FILE_PATH]
    200 SITE CHMOD command ok.
    
    0 讨论(0)
  • 2020-12-03 16:22

    Use sendCommand("SITE LRECL=242 BLKSIZE=0 RECFM=FB");

    0 讨论(0)
  • 2020-12-03 16:24

    You can try our Rebex FTP component:

    // create client and connect 
    Ftp client = new Ftp();
    client.Connect("ftp.example.org");
    client.Login("username", "password");
    
    // send SITE command
    // note that QUOTE and SITE are ommited. QUOTE is command line ftp syntax only.
    client.Site("LRECL=132 RECFM=FB");
    
    // send SYST command
    client.SendCommand("SYST");
    FtpResponse response = client.ReadResponse();
    if (response.Group != 2) 
      ; // handle error 
    
    // disconnect 
    client.Disconnect();
    
    0 讨论(0)
提交回复
热议问题