Partager via


Sample code for parsing FtpwebRequest response for ListDirectoryDetails

This posting is valid for .Net frameworks 2.0 (Currently released as Whidbey Beta1)

ResponseStream of FtpWebResponse provides the raw data bytes to the user, s

ome of you had asked that it would be more useful to provide methods which return list of directory and files on ListDirectory request to the server. Current .Net frameworks doesn't support this, so here is some sample code I had written for parsing, in general I found it works very well against most of the server. But just to make sure it is not extensively tested, so treat only as sample, its not guaranteed to work against every server.

using System;
using System.IO;
using System.Net;
using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;

   public struct FileStruct
{
public string Flags;
public string Owner;
public string Group;
public bool IsDirectory;
public DateTime CreateTime;
public string Name;
}
public enum FileListStyle{
UnixStyle,
WindowsStyle,
Unknown
}

public class ParseListDirectory
{
public static void Main(string[] args)
{
if(args.Length < 1)
{
Console.WriteLine("\n Usage FTPListDirParser <uriString>");
return;
}
try
{
FtpWebRequest ftpclientRequest = WebRequest.Create(args[0]) as FtpWebRequest;
ftpclientRequest.Method = FtpMethods.ListDirectoryDetails;
ftpclientRequest.Proxy = null;
FtpWebResponse response = ftpclientRequest.GetResponse() as FtpWebResponse;
StreamReader sr = new StreamReader(response.GetResponseStream(), System.Text.Encoding.ASCII);
string Datastring = sr.ReadToEnd();
response.Close();

FileStruct[] list = (new ParseListDirectory()).GetList(Datastring);
Console.WriteLine ("------------After Parsing-----------");
foreach(FileStruct thisstruct in list)
{
if(thisstruct.IsDirectory)
Console.WriteLine("<DIR> "+thisstruct.Name+","+thisstruct.Owner+","+thisstruct.Flags+","+thisstruct.CreateTime);
else
Console.WriteLine(thisstruct.Name+","+thisstruct.Owner+","+thisstruct.Flags+","+thisstruct.CreateTime);
}
}
catch(Exception e)
{
Console.WriteLine(e);
}
}

private FileStruct[] GetList(string datastring)
{
List<FileStruct> myListArray = new List<FileStruct>();
string[] dataRecords = datastring.Split('\n');
FileListStyle _directoryListStyle = GuessFileListStyle(dataRecords);
foreach (string s in dataRecords)
{
if (_directoryListStyle != FileListStyle.Unknown && s != "")
{
FileStruct f = new FileStruct();
f.Name = "..";
switch (_directoryListStyle)
{
case FileListStyle.UnixStyle:
f = ParseFileStructFromUnixStyleRecord(s);
break;
case FileListStyle.WindowsStyle:
f = ParseFileStructFromWindowsStyleRecord(s);
break;
}
if (!(f.Name == "." || f.Name == ".."))
{
myListArray.Add(f);
}
}
}
return myListArray.ToArray(); ;
}

 private FileStruct ParseFileStructFromWindowsStyleRecord(string Record)
{
///Assuming the record style as
/// 02-03-04 07:46PM <DIR> Append
FileStruct f = new FileStruct();
string processstr = Record.Trim();
string dateStr = processstr.Substring(0,8);
processstr = (processstr.Substring(8, processstr.Length - 8)).Trim();
string timeStr = processstr.Substring(0, 7);
processstr = (processstr.Substring(7, processstr.Length - 7)).Trim();
f.CreateTime = DateTime.Parse(dateStr + " " + timeStr);
if (processstr.Substring(0,5) == "<DIR>")
{
f.IsDirectory = true;
processstr = (processstr.Substring(5, processstr.Length - 5)).Trim();
}
else
{
string[] strs = processstr.Split(new char[] { ' ' }, true);
processstr = strs[1].Trim();
f.IsDirectory = false;
}
f.Name = processstr; //Rest is name
return f;
}

 public FileListStyle GuessFileListStyle(string[] recordList)
{
foreach (string s in recordList)
{
if(s.Length > 10
&& Regex.IsMatch(s.Substring(0,10),"(-|d)(-|r)(-|w)(-|x)(-|r)(-|w)(-|x)(-|r)(-|w)(-|x)"))
{
return FileListStyle.UnixStyle;
}
else if (s.Length > 8
&& Regex.IsMatch(s.Substring(0, 8), "[0-9][0-9]-[0-9][0-9]-[0-9][0-9]"))
{
return FileListStyle.WindowsStyle;
}
}
return FileListStyle.Unknown;
}

 private FileStruct ParseFileStructFromUnixStyleRecord(string Record)
{
///Assuming record style as
/// dr-xr-xr-x 1 owner group 0 Nov 25 2002 bussys
FileStruct f= new FileStruct();
string processstr = Record.Trim();
f.Flags = processstr.Substring(0,9);
f.IsDirectory = (f.Flags[0] == 'd');
processstr = (processstr.Substring(11)).Trim();
_cutSubstringFromStringWithTrim(ref processstr,' ',0); //skip one part
f.Owner = _cutSubstringFromStringWithTrim(ref processstr,' ',0);
f.Group = _cutSubstringFromStringWithTrim(ref processstr,' ',0);
_cutSubstringFromStringWithTrim(ref processstr,' ',0); //skip one part
f.CreateTime = DateTime.Parse(_cutSubstringFromStringWithTrim(ref processstr,' ',8));
f.Name = processstr; //Rest of the part is name
return f;
}

     private string _cutSubstringFromStringWithTrim(ref string s, char c, int startIndex)
{
int pos1 = s.IndexOf(c, startIndex);
string retString = s.Substring(0,pos1);
s = (s.Substring(pos1)).Trim();
return retString;
}
}
This posting is provided "AS IS" with no warranties, and confers no rights

Comments

  • Anonymous
    November 09, 2006
    Getting the following error while doing this:   using (FtpWebResponse response = (FtpWebResponse)ftp.GetResponse())The Remote Server returned an error:(550) File unavailable(e.g., file not found, no access)

  • Anonymous
    May 08, 2007
    Replace: string[] strs = processstr.Split(new char[] { ' ' }, true);   processstr = strs[1]; By: processstr = processstr.Remove(0,processstr.IndexOf(' ') + 1); Otherwise you truncate file name with white spaces. f.CreateTime = DateTime.Parse(dateStr + " " + timeStr); Can throw a InvalidFormatException. Replace by f.CreateTime = DateTime.Parse(dateStr + " " + timeStr, CultureInfo.GetCultureInfo("en-US")); Thanks for you code. He help me.

  • Anonymous
    June 17, 2007
    The comment has been removed

  • Anonymous
    September 24, 2007
    The comment has been removed

  • Anonymous
    September 24, 2007
    The comment has been removed

  • Anonymous
    May 06, 2008
    Stop! Try to read this interested book:,

  • Anonymous
    June 15, 2008
    Try to look here and may be you find what do you want:,

  • Anonymous
    June 25, 2008
    Of course, but what do you think about that?,

  • Anonymous
    October 07, 2008
    Do you know what is refactoring?

  • Anonymous
    October 24, 2008
    Do you have this sample written in VB code?

  • Anonymous
    April 28, 2009
    The comment has been removed

  • Anonymous
    May 12, 2009
    DeMi's alternative code seems to work as well (and seems a little neater!).  The only bug I've found is changing the 2nd occurence of:return ParseMatch(match.Groups, ListStyle.Unix);toreturn ParseMatch(match.Groups, ListStyle.Windows);

  • Anonymous
    June 09, 2009
    Regex for FileZilla Server;    private Regex fileZilla = new Regex(@"(?<dir>[-dl])(?<ownerSec>)[-r][-w]-x[-r][-w]-x[-r][-w][-x]s+(?:d)s+(?<owner>w+)s+(?<group>w+)s+(?<size>d+)s+(?<month>w+)s+(?<day>d{1,2})s+(?<year>w+)s+(?<name>.*)$");           match = fileZilla.Match(line);           if (match.Success)           {               return ParseMatch(match.Groups, ListStyle.Unix);           }

  • Anonymous
    July 04, 2009
    これから家出したい少女や、現在家出中の娘とそんな娘を助けたい人を繋げるSOS掲示板です。10代、20代の女の子が家庭内の問題などでやむなく家出している子が多数書き込みしています。女の子リストを見て彼女たちにアプローチしてみませんか

  • Anonymous
    July 05, 2009
    The comment has been removed

  • Anonymous
    July 06, 2009
    The comment has been removed

  • Anonymous
    July 21, 2009
    If your ftpsite requires authentication, useFtpWebRequest ftpclientRequest = WebRequest.Create(args[0]) as FtpWebRequest;ftpclientRequest.Credentials = new NetworkCredential("username", "password");

  • Anonymous
    August 11, 2009
    即ハメセレブは完全無料でご利用できる出会いコミュニティです。今までにない実績で、あなたの希望に合った人をお探しします。毎月考えられない豪華なイベントを開催しているので出会いを保障します

  • Anonymous
    May 10, 2010
    Thank you, for code and first comment, but how can i know a size file?

  • Anonymous
    June 24, 2010
    This snippet does not work for meFtpWebRequest ftpclientRequest = WebRequest.Create("https://sftp.dts.ca.gov") as FtpWebRequest;               ftpclientRequest.Method = FtpMethods.ListDirectoryDetails;This is the errorError 14 The name 'FtpMethods' does not exist in the current context C:Documents and SettingsmvtwvMy DocumentsVisual Studio 2005ProjectsFile Generation SystemFile Generation Systemcourt.cs 2339 43 File Generation SystemI have checked all my name spaces and they are fine.

  • Anonymous
    August 30, 2010
    You may have a look at the great opensource lib edtFTPnet from Enterprise Distributed Technologies ( www.enterprisedt.com) - they adressed the problem with unix style and when the file is created the current year - and therefore the datestamp is not holding year - besides other things is adressed as well - so for You who need inspiration - look into that great piece og code - really helped me a lot with some simple FTP requests where I only needed a list of files and after that being able to sort the list by date.

  • Anonymous
    February 22, 2012
    hello i have question ,why  WebRequestMethods.Ftp.ListDirectory; dont show htaccess file ,and how i can solve this,thx

  • Anonymous
    October 03, 2012
    Adarsh, Thank you so much. It is working perfect for me. Was looking for such kind of an article for a long time.

  • Anonymous
    April 23, 2014
    Great solution. Thanks a lot.I added size this way:Modified FileStruct:public struct FileStruct   {       public string Flags;       public string Owner;       public string Group;       public bool IsDirectory;       public DateTime CreateTime;       public long Size;       public string Name;   }In ParseFileStructFromUnixStyleRecord, changed this:_cutSubstringFromStringWithTrim(ref processstr, ' ', 0);   //skip one partwith this:f.Size = Convert.ToInt64(_cutSubstringFromStringWithTrim(ref processstr, ' ', 0));And in ParseFileStructFromWindowsStyleRecord this:string[] strs = processstr.Split(new char[] { ' ' }, true);processstr = strs[1].Trim();with this:f.Size = Convert.ToInt64(processstr.Substring(0, processstr.IndexOf(' ')).Trim());processstr = processstr.Remove(0, processstr.IndexOf(' ') + 1);(This include the changes proposed by Steffen Xavier xsteffen@ict7.com )Just my two cents.