I wrote the following code a long time ago to determine if an FTP directory exists:
public bool DirectoryExists(string directory)
{
try
{
FtpWebRequest request = GetRequest(directory);
request.Method = WebRequestMethods.Ftp.ListDirectory;
using (FtpWebResponse response = request.GetResponse() as FtpWebResponse)
{
StreamReader sr = new StreamReader(response.GetResponseStream(), System.Text.Encoding.ASCII);
sr.ReadToEnd();
sr.Close();
response.Close();
}
return true;
}
catch { }
return false;
}
protected FtpWebRequest GetRequest(string filename = "")
{
FtpWebRequest request = WebRequest.Create(_host.GetUrl(filename)) as FtpWebRequest;
request.Credentials = new NetworkCredential(Username, Password);
request.Proxy = null;
request.KeepAlive = false;
return request;
}
This code has worked for several years, but today it doesn't. When testing a directory that does not exist, the code in DirectoryExists()
no longer throws an exception, and the method incorrectly returns true
.
If I assign the results of sr.ReadToEnd()
to a string, it is an empty string.
In this case, the code _host.GetUrl(filename)
returned "ftp://www.mydomain.com/Articles/winforms/accessing-the-windows-registry". This is the expected value. And still my DirectoryExists() method does not throw an exception when this path does not exist on the server. I even passed this non-existing directory to a method that uses WebRequestMethods.Ftp.ListDirectoryDetails
to build a directory listing. This method simply returns an empty listing and also throws no exception.
I believe I first encountered this issue when I moved my code to a new computer with Visual Studio 2013. I'm using .NET 4.5 and got the same behavior when using .NET 4.5.1.
Questions:
Why doesn't this code, which has worked for years and uses the same technique used on most of the online examples I found, work? And what could possibly cause this code to suddenly stop working?
Is there a way to detect for the presence of a directory that works? I suppose the other approach is to scan the parent directory, although the logic would need to be different when the routine is supposed to verify the root directory.
The default vsftpd login directory for a normal user is the home directory of the system normal user; and the default vsftpd login directory for the anonymous user is /var/ftp .
dir -R = Lists all files in current directory and sub directories. dir -S = Lists files in bare format in alphabetic order. Exits from FTP. Get file from the remote computer.
I managed to reproduce your error on another site I have access to. After some playing around, here's my conclusion:-
When you make a FtpWebRequest
with a FTP URL that does NOT end with a /
, such as:
ftp://ftp.someftp.com/somefolder/invalidfolder
AND you specified WebRequestMethods.Ftp.ListDirectory
as the method, then what it does behind the scene is to run the following command:
NLST "somefolder/invalidfolder"
Normally, NLST will list the contents of the specified folder, and throws an exception if the folder does not exist. But because you did not specify a /
at the end of invalidfolder
, NLST will think that invalidfolder
may actually be a file (or a filename pattern). If it manages to find a folder named invalidfolder
, then and only then will it treat it as a folder. Otherwise it will try to search a file named invalidfolder
underneath the parent folder somefolder
. If the file does not exist, then one of the following will occur, depending on which FTP server software (and its configurations) is running:
In your case, the FTP server returns the latter response, and your code falls over.
The solution? Just add some validation code to make sure the ftp folder you are trying to access always has a /
at the end. Something like the following:-
if (!directory.EndsWith('/'))
directory += '/';
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With