C# FTP Size command doesn't work on all FTP se

2019-07-17 06:44发布

问题:

I am having some trouble with a very simple snippet of code:

     private long getFTPLogLength()
    {
        long size;
        FtpWebRequest ftpRequest = (FtpWebRequest)FtpWebRequest.Create(new Uri(ftpURL));
        ftpRequest.Credentials = new NetworkCredential(ftpUsername, ftpPassword);
        try
        {
            ftpRequest.ReadWriteTimeout = 6000;
            ftpRequest.Method = WebRequestMethods.Ftp.GetFileSize;
            FtpWebResponse respSize = (FtpWebResponse)ftpRequest.GetResponse();
            size = respSize.ContentLength;
            respSize.Close();
        }
        catch (Exception ex)
        {
            logLog.writeEntry(4, "Error getting logsize from FTP: " + ex.Message);
            size = 0;
        }
        return size;
    }

The point of this method is to obviously grab the length of a particular file. The issue here is that on some servers (namely gameservers.com servers), this code does not work. It works on every other server type I can test.

I did find this while looking for some help on it: C# FTP 550 error and I have tried with one slash and two, and I still get the same result. To take this a step further, I only get the 550 error when I do GetFileSize (SIZE). If I do GetDateTime (MDTM), it does not throw this error. This would leave you to believe that the SIZE command has been disabled, or I don't have access to use it, however if I connect to the server with FileZilla (or any client for that matter), and run SIZE games_mp.log it works just fine.

Here is a screenshot of the debugger after the exception (note, I bought this game server for the very purpose of fixing this bug, so the credentials are left in place intentionally for your testing pleasure).

Any information that could help me figure out what I need to do to make this work with their servers would be helpful. Hopefully I am missing something simple. :)

After some more testing, if I let FileZilla timeout, them I run the command manually, I get an error about SIZE not being supported in ASCII mode, but if I start a new connection to the server it works just fine.

Fresh connection to server:

Command after timeout:

Hopefully this means something to someone....

回答1:

(Note: I wrote the FTP server software here and have access to the raw server logs of what happened)

The issue here is rather simple, when you attempted the SIZE command in Filezilla, you were in binary transfer mode. When you attempted to run this command via your client (or after Filezilla reconnected), you were in ASCII transfer mode.

Looking at the actual access logs, it seems that on the initial connection, Filezilla executes 'TYPE I' followed by 'MLSD'. When it reconnects afterwards, it doesn't attempt the MLSD command again, so it doesn't bother to execute 'TYPE I'.

Computing the actual file size in ASCII mode is fairly resource intensive (especially considering that your code by nature is going to attempt this command quite frequently). It requires that we parse the entire file and replace all the line ending characters. This not something that we'd want to do all the time on a busy FTP server.

This behavior is actually accounted for by the RFC:

The presence of the 550 error response to a SIZE command MUST NOT be taken by the client as an indication that the file cannot be transferred in the current MODE and TYPE. A server may generate this error for other reasons -- for instance if the processing overhead is considered too great.

In ASCII mode:

ncftp / > quote size games_mp.log
> quote size games_mp.log

Cmd: size games_mp.log
550: SIZE not allowed in ASCII mode.
SIZE not allowed in ASCII mode.

In BINARY mode:

ncftp / > quote size games_mp.log
> quote size games_mp.log

Cmd: size games_mp.log
213: 134901
134901

So, your actual fix here would be to switch to binary mode before you try and get the file size.

We'd also greatly prefer that you change the password on your account. We've seen significant abuse from open FTP accounts in the past (some people feel the need to fill up any FTP account they find with various types of pirated content).



回答2:

Ftp SIZE command does not exists in basic FTP RFC, and added only in RFC 3659. And, error 550 for FTP is 'action unavailable', i.e. server tells that it just doesn't support such command.



回答3:

If the server supports the FEAT command issue it to the server and see if it contains 'SIZE' in the result list. This should tell you definitely if the server supports the SIZE command. This ofcourse assumes the server supports the FEAT command itself.



标签: c# ftp filesize