1

I want to check remote folder's content, and determine if the particular file exists in this folder (I'm checking only by filename, so chill :D)

Example: I want to check if in the folder /testftp contains a textfile.txt file.

I'm doing this to get folder content:

      FtpWebRequest request = (FtpWebRequest)WebRequest.Create("myftpaddress");
        request.Method = WebRequestMethods.Ftp.ListDirectoryDetails;


        request.Credentials = new NetworkCredential("uid", "pass");

        FtpWebResponse response = (FtpWebResponse)request.GetResponse();

        Stream responseStream = response.GetResponseStream();
        StreamReader reader = new StreamReader(responseStream);
        Console.WriteLine(reader.ReadToEnd());

        Console.WriteLine("Directory List Complete, status {0}", response.StatusDescription);

        reader.Close();
        response.Close(); 

it writes in console:

-rw-r--r--   1 6668   userftp 91137 jul 16 23:20 file1.txt
-rw-r--r--   1 468    userftp   137 jul 16 18:40 file2.swf

and it writes full stream response into console, how to get only file names? Is there an easier way?

Eric J.
  • 147,927
  • 63
  • 340
  • 553
pawel
  • 5,976
  • 15
  • 46
  • 68
  • 1
    your question is a duplicate of http://stackoverflow.com/questions/347897/how-to-check-if-file-exists-on-ftp-before-ftpwebrequest – HatSoft Jul 16 '12 at 22:36

2 Answers2

1

It would be easier to just try and download the file. If you get StatusCode indicating that the file does not exist, you know it was not there.

Probably less work than filtering the result of ListDirectoryDetails.

Update

To clarify, all you need to do is this:

FtpWebResponse response = (FtpWebResponse) request.GetResponse();
bool fileExists = (response.StatusCode != BAD_COMMAND);

I think BAD_COMMAND would be FtpStatusCode.CantOpenData but I'm not sure. That's easily tested.

Eric J.
  • 147,927
  • 63
  • 340
  • 553
  • If the file is present, you would then incur the cost of downloading it. – Monroe Thomas Jul 16 '12 at 22:42
  • Only if you call `reader.ReadToEnd()`, which is not needed just to determine whether the resource exists. – Eric J. Jul 16 '12 at 22:55
  • I don't understand how not calling `reader.ReaderToEnd()` prevents the FTP server from sending the contents of the file? Sure, closing the response stream may close the connection before all bytes are received. – Monroe Thomas Jul 16 '12 at 23:21
  • You only need the response header to be available on the client before fileExists is assigned a value. If the file does not exist, that's all you get. If the file does exist, you'll probably get a few milliseconds of response body before the connection is closed. Those few milliseconds may amount to more or less data than you would get if you do the full listing. – Eric J. Jul 16 '12 at 23:28
  • 1
    OK, that matches my intuition then. Hopefully there are no big TCP windows or a large bandwidth delay product. Anyway, looks like HatSoft pointed at the right answer... use `WebRequestMethods.Ftp.GetDateTimestamp`, which is analogous to your answer, but without the potential for a large response. – Monroe Thomas Jul 16 '12 at 23:48
  • Okay, so I have to create a request every time when I want to check one file? What if I'll have 100 files? 100 requests? : ) – pawel Jul 17 '12 at 08:58
0
string listing = reader.ReadToEnd();

// find all occurrences of the fileName and make sure
// it is bounded by white space or string boundary.

int startIndex = 0;
bool exists = false;
while (true)
{
    int index = listing.IndexOf(fileName, startIndex);
    if (index == -1) break;

    int leadingIndex = index - 1;
    int trailingIndex = index + fileName.Length;

    if ((leadingIndex == -1 || Char.IsWhiteSpace(listing[leadingIndex]) &&
        (trailingIndex == list.Length || Char.IsWhiteSpace(listing[trailingIndex]))
    {
        exists = true;
        break;
    }

    startIndex = trailingIndex;
}

Regex version:

string pattern = string.Format("(^|\\s){0}(\\s|$)", Regex.Escape(fileName));
Regex regex = new Regex(pattern);

string listing = reader.ReadToEnd();
bool exists = regex.IsMatch(listing);
Monroe Thomas
  • 4,962
  • 1
  • 17
  • 21
  • 1
    What if the listing contains the file `textfile.txt.old`? That will incorrectly match with your code. – Eric J. Jul 16 '12 at 22:39
  • You can use RegEx to do a match with surrounding white space/newline but simply testing for the presence of the file by trying to download it is less work :-) – Eric J. Jul 16 '12 at 22:40
  • I've written in first post - i'm cheking only filenames and they always will be different, cause I will be comparing randomized md5 crypted strings, so that's all what i need? – pawel Jul 16 '12 at 22:45
  • @pawel Hopefully. I've adjusted my answer to accomodate Eric's concern, although it isn't as short as a RegEx (which will take me a few more moments to put together, as I use RegEx's once every 6 months and can never remember the details for a given platform; I think you'd have to escape the fileName within the RegEx.) – Monroe Thomas Jul 16 '12 at 22:53