https://netftp.codeplex.com/

        /// <summary>
/// Gets a file listing from the server. Each FtpListItem object returned
/// contains information about the file that was able to be retrieved. If
/// a DateTime property is equal to DateTime.MinValue then it means the
/// date in question was not able to be retrieved. If the Size property
/// is equal to 0 then it means the size of the object could also not
/// be retrieved.
/// 读取文件或文件夹
/// </summary>
/// <param name="path">The path of the directory to list</param>
/// <param name="options">Options that dictacte how a list is performed and what information is gathered.根据选项读取文件或文件夹或其文件的属性</param>
/// <returns>An array of FtpListItem objects</returns>
/// <example><code source="..\Examples\GetListing.cs" lang="cs" /></example>
public FtpListItem[] GetListing(string path, FtpListOption options) {
FtpListItem item = null;
List<FtpListItem> lst = new List<FtpListItem>();
List<string> rawlisting = new List<string>();
string listcmd = null;
string pwd = GetWorkingDirectory();
string buf = null; if (path == null || path.Trim().Length == 0) {
pwd = GetWorkingDirectory();
if (pwd != null && pwd.Trim().Length > 0)
path = pwd;
else
path = "./";
}
else if (!path.StartsWith("/") && pwd != null && pwd.Trim().Length > 0) {
if (path.StartsWith("./"))
path = path.Remove(0, 2);
path = string.Format("{0}/{1}", pwd, path).GetFtpPath();
} // MLSD provides a machine parsable format with more
// accurate information than most of the UNIX long list
// formats which translates to more effcient file listings
// so always prefer MLSD over LIST unless the caller of this
// method overrides it with the ForceList option
// !=
if ((options & FtpListOption.ForceList) == FtpListOption.ForceList && HasFeature(FtpCapability.MLSD))
{
listcmd = "MLSD";
}
else
{
if ((options & FtpListOption.UseLS) == FtpListOption.UseLS)
{
listcmd = "LS";
}
else if ((options & FtpListOption.NameList) == FtpListOption.NameList)
{
listcmd = "NLST"; //读取文件名
}
else
{
string listopts = "";
listcmd = "LIST"; //读取所有文件夹文件
if ((options & FtpListOption.AllFiles) == FtpListOption.AllFiles)
listopts += "a"; if ((options & FtpListOption.Recursive) == FtpListOption.Recursive)
listopts += "R"; if (listopts.Length > 0)
listcmd += " -" + listopts;
}
} if((options & FtpListOption.NoPath) != FtpListOption.NoPath)
{
listcmd = string.Format("{0} {1}", listcmd, path.GetFtpPath());
} lock (m_lock)
{
Execute("TYPE I");
//NLST /htdocs 读文件
// read in raw file listing MLSD /htdocs
using (FtpDataStream stream = OpenDataStream(listcmd, 0)) {
try {
while ((buf = stream.ReadLine(Encoding)) != null) {
if (buf.Length > 0)
{
rawlisting.Add(buf);
FtpTrace.WriteLine(buf);
}
//rawlisting.Add(buf);
//FtpTrace.WriteLine(buf);
}
}
finally {
stream.Close();
}
}
} //根据上一个循环来读文件或文件夹的属性
for (int i = 0; i < rawlisting.Count; i++) {
buf = rawlisting[i];
if ((options & FtpListOption.NameList) == FtpListOption.NameList) {
// if NLST was used we only have a file name so
// there is nothing to parse.
item = new FtpListItem() {
FullName = buf
}; if (DirectoryExists(item.FullName))
item.Type = FtpFileSystemObjectType.Directory;
else
item.Type = FtpFileSystemObjectType.File; lst.Add(item);
}
else {
// if this is a result of LIST -R then the path will be spit out
// before each block of objects
if (listcmd.StartsWith("LIST") && (options & FtpListOption.Recursive) == FtpListOption.Recursive) {
if (buf.StartsWith("/") && buf.EndsWith(":")) {
path = buf.TrimEnd(':');
continue;
}
} // if the next line in the listing starts with spaces
// it is assumed to be a continuation of the current line
if (i + 1 < rawlisting.Count && (rawlisting[i + 1].StartsWith("\t") || rawlisting[i + 1].StartsWith(" ")))
buf += rawlisting[++i]; item = FtpListItem.Parse(path, buf, m_caps); //重复了文件夹名称
// FtpListItem.Parse() returns null if the line
// could not be parsed
if (item != null && (item.Name != "." && item.Name != ".."))
lst.Add(item);
else
FtpTrace.WriteLine("Failed to parse file listing: " + buf);
} // load extended information that wasn't available if the list options flags say to do so.
if (item != null) {
// try to dereference symbolic links if the appropriate list
// option was passed
if (item.Type == FtpFileSystemObjectType.Link && (options & FtpListOption.DerefLinks) == FtpListOption.DerefLinks) {
item.LinkObject = DereferenceLink(item);
} if ((options & FtpListOption.Modify) == FtpListOption.Modify && HasFeature(FtpCapability.MDTM)) {
// if the modified date was not loaded or the modified date is more than a day in the future
// and the server supports the MDTM command, load the modified date.
// most servers do not support retrieving the modified date
// of a directory but we try any way.
if (item.Modified == DateTime.MinValue || listcmd.StartsWith("LIST")) {
DateTime modify; if (item.Type == FtpFileSystemObjectType.Directory)
FtpTrace.WriteLine("Trying to retrieve modification time of a directory, some servers don't like this..."); if ((modify = GetModifiedTime(item.FullName)) != DateTime.MinValue)
item.Modified = modify;
}
} if ((options & FtpListOption.Size) == FtpListOption.Size && HasFeature(FtpCapability.SIZE)) {
// if no size was parsed, the object is a file and the server
// supports the SIZE command, then load the file size
if (item.Size == -1) {
if (item.Type != FtpFileSystemObjectType.Directory) {
item.Size = GetFileSize(item.FullName);
}
else {
item.Size = 0;
}
}
}
}
} return lst.ToArray();
} /// <summary>
/// Creates a valid FTP path by appending the specified segments to this string
/// </summary>
/// <param name="path">This string</param>
/// <param name="segments">The path segments to append</param>
/// <returns>A valid FTP path</returns>
public static string GetFtpPath(this string path, params string[] segments) {
if (String.IsNullOrEmpty(path))
path = "./"; foreach (string part in segments) {
if (part != null) {
if (path.Length > 0 && !path.EndsWith("/"))
path += "/";
//path += Regex.Replace(part.Replace('\\', '/'), "[/]+", "/").TrimEnd('/'); //变成重复
}
} path = Regex.Replace(path.Replace('\\', '/'), "[/]+", "/").TrimEnd('/');
if (path.Length == 0)
path = "/"; /*if (!path.StartsWith("/") || !path.StartsWith("./"))
path = "./" + path;*/ return path;
}

  测试

       /// <summary>
/// 涂聚文
/// Geovin Du
/// 2017-08-02
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button1_Click(object sender, EventArgs e)
{
FtpClient client = new FtpClient();
client.Host = ftpServer;
client.Encoding = System.Text.Encoding.GetEncoding("GB2312");
// if you don't specify login credentials, we use the "anonymous" user account
client.Credentials = new NetworkCredential(user, pwd); // begin connecting to the server
client.Connect();
//client.SetWorkingDirectory("/htdocs/"); //文件夹和文件(未成功)
//FtpListOption.NameList 当前文件夹下的文件
//FtpListOption.AllFiles 当前文件夹下文件和文件夹
FtpListItem[] items = client.GetListing("/htdocs/", FtpListOption.AllFiles);//根目录下可以。 AllFiles
this.dataGridView1.DataSource = items; //获取的是所有文件名
//client.SetWorkingDirectory("/htdocs/");
//string[] items = client.GetNameListing();
//List<FileInfoList> list = new List<FileInfoList>();
//foreach (string str in items)
//{
// FileInfoList info = new FileInfoList();
// info.Name = str;
// info.Date = DateTime.Now;
// list.Add(info);
//}
//this.dataGridView1.DataSource = list;
}
} /// <summary>
///
/// </summary>
public class FileInfoList
{
public string Name { set; get; } public DateTime Date { set; get; } }

 https://github.com/hgupta9/FluentFTP

		/// <summary>
/// Gets a file listing from the server. Each <see cref="FtpListItem"/> object returned
/// contains information about the file that was able to be retrieved.
/// 读取文件和文件夹
/// 涂聚文 2017-08-02 小小修改
/// </summary>
/// <remarks>
/// If a <see cref="DateTime"/> property is equal to <see cref="DateTime.MinValue"/> then it means the
/// date in question was not able to be retrieved. If the <see cref="FtpListItem.Size"/> property
/// is equal to 0, then it means the size of the object could also not
/// be retrieved.
/// </remarks>
/// <param name="path">The path of the directory to list</param>
/// <param name="options">Options that dictacte how a list is performed and what information is gathered.</param>
/// <returns>An array of FtpListItem objects</returns>
/// <example><code source="..\Examples\GetListing.cs" lang="cs" /></example>
public FtpListItem[] GetListing(string path, FtpListOption options) { FtpTrace.WriteFunc("GetListing", new object[] { path, options }); FtpListItem item = null;
List<FtpListItem> lst = new List<FtpListItem>();
List<string> rawlisting = new List<string>();
string listcmd = null;
string buf = null; // read flags
bool isIncludeSelf = (options & FtpListOption.IncludeSelfAndParent) == FtpListOption.IncludeSelfAndParent;
bool isForceList = (options & FtpListOption.ForceList) == FtpListOption.ForceList;
bool isNoPath = (options & FtpListOption.NoPath) == FtpListOption.NoPath;
bool isNameList = (options & FtpListOption.NameList) == FtpListOption.NameList;
bool isUseLS = (options & FtpListOption.UseLS) == FtpListOption.UseLS;
bool isAllFiles = (options & FtpListOption.AllFiles) == FtpListOption.AllFiles;
bool isRecursive = (options & FtpListOption.Recursive) == FtpListOption.Recursive && RecursiveList;
bool isDerefLinks = (options & FtpListOption.DerefLinks) == FtpListOption.DerefLinks;
bool isGetModified = (options & FtpListOption.Modify) == FtpListOption.Modify;
bool isGetSize = (options & FtpListOption.Size) == FtpListOption.Size; // calc path to request
path = GetAbsolutePath(path); // MLSD provides a machine readable format with 100% accurate information
// so always prefer MLSD over LIST unless the caller of this method overrides it with the ForceList option
bool machineList = false; //||
if ((!isForceList & m_parser == FtpParser.Machine) && HasFeature(FtpCapability.MLSD)) {
listcmd = "MLSD";
machineList = true;
} else {
if (isUseLS) {
listcmd = "LS";
} else if (isNameList) {
listcmd = "NLST";
} else {
string listopts = ""; listcmd = "LIST"; if (isAllFiles)
listopts += "a"; //读取所有文件夹和文件 if (isRecursive)
listopts += "R"; if (listopts.Length > 0)
listcmd += " -" + listopts;
}
} if (!isNoPath) {
listcmd = (listcmd + " " + path.GetFtpPath());
} #if !CORE14
lock (m_lock) {
#endif
Execute("TYPE I");
//读取出文件夹或文件 读取所有文件夹和文件 LIST a
// read in raw file listing
using (FtpDataStream stream = OpenDataStream(listcmd, 0)) {
try {
FtpTrace.WriteLine(FtpTraceLevel.Verbose, "+---------------------------------------+"); if (this.BulkListing) { // increases performance of GetListing by reading multiple lines of the file listing at once
foreach (var line in stream.ReadAllLines(Encoding, this.BulkListingLength)) {
if (!FtpExtensions.IsNullOrWhiteSpace(line)) {
rawlisting.Add(line);
FtpTrace.WriteLine(FtpTraceLevel.Verbose, "Listing: " + line);
}
} } else { // GetListing will read file listings line-by-line (actually byte-by-byte)
while ((buf = stream.ReadLine(Encoding)) != null) {
if (buf.Length > 0) {
rawlisting.Add(buf);
FtpTrace.WriteLine(FtpTraceLevel.Verbose, "Listing: " + buf);
}
}
} FtpTrace.WriteLine(FtpTraceLevel.Verbose, "-----------------------------------------"); } finally {
stream.Close();
}
}
#if !CORE14
}
#endif
//在上循环中读取文件或文件夹属性
for (int i = 0; i < rawlisting.Count; i++) {
buf = rawlisting[i]; if (isNameList) { // if NLST was used we only have a file name so
// there is nothing to parse.
item = new FtpListItem() {
FullName = buf
}; if (DirectoryExists(item.FullName))
item.Type = FtpFileSystemObjectType.Directory;
else
item.Type = FtpFileSystemObjectType.File; lst.Add(item); } else { // if this is a result of LIST -R then the path will be spit out
// before each block of objects
if (listcmd.StartsWith("LIST") && isRecursive) {
if (buf.StartsWith("/") && buf.EndsWith(":")) {
path = buf.TrimEnd(':');
continue;
}
} // if the next line in the listing starts with spaces
// it is assumed to be a continuation of the current line
if (i + 1 < rawlisting.Count && (rawlisting[i + 1].StartsWith("\t") || rawlisting[i + 1].StartsWith(" ")))
buf += rawlisting[++i]; try {
item = m_listParser.ParseSingleLine(path, buf, m_caps, machineList);
} catch (FtpListParser.CriticalListParseException) {
FtpTrace.WriteStatus(FtpTraceLevel.Verbose, "Restarting parsing from first entry in list");
i = -1;
lst.Clear();
continue;
} // FtpListItem.Parse() returns null if the line
// could not be parsed
if (item != null) {
if (isIncludeSelf || !(item.Name == "." || item.Name == "..")) {
lst.Add(item);
} else {
//FtpTrace.WriteStatus(FtpTraceLevel.Verbose, "Skipped self or parent item: " + item.Name);
}
} else {
FtpTrace.WriteStatus(FtpTraceLevel.Warn, "Failed to parse file listing: " + buf);
}
} // load extended information that wasn't available if the list options flags say to do so.
if (item != null) { // try to dereference symbolic links if the appropriate list
// option was passed
if (item.Type == FtpFileSystemObjectType.Link && isDerefLinks) {
item.LinkObject = DereferenceLink(item);
} // if need to get file modified date
if (isGetModified && HasFeature(FtpCapability.MDTM)) { // if the modified date was not loaded or the modified date is more than a day in the future
// and the server supports the MDTM command, load the modified date.
// most servers do not support retrieving the modified date
// of a directory but we try any way.
if (item.Modified == DateTime.MinValue || listcmd.StartsWith("LIST")) {
DateTime modify; if (item.Type == FtpFileSystemObjectType.Directory)
FtpTrace.WriteStatus(FtpTraceLevel.Verbose, "Trying to retrieve modification time of a directory, some servers don't like this..."); if ((modify = GetModifiedTime(item.FullName)) != DateTime.MinValue)
item.Modified = modify;
}
} // if need to get file size
if (isGetSize && HasFeature(FtpCapability.SIZE)) { // if no size was parsed, the object is a file and the server
// supports the SIZE command, then load the file size
if (item.Size == -1) {
if (item.Type != FtpFileSystemObjectType.Directory) {
item.Size = GetFileSize(item.FullName); //尺寸要换算一下
} else {
item.Size = 0;
}
}
}
}
} return lst.ToArray();
} /// <summary>
/// Creates a valid FTP path by appending the specified segments to this string
/// 涂聚文 2017-08-02 小小修改
/// </summary>
/// <param name="path">This string</param>
/// <param name="segments">The path segments to append</param>
/// <returns>A valid FTP path</returns>
public static string GetFtpPath(this string path, params string[] segments) {
if (String.IsNullOrEmpty(path))
path = "./"; foreach (string part in segments) {
if (part != null) {
if (path.Length > 0 && !path.EndsWith("/"))
path += "/";
//path = Regex.Replace(part.Replace('\\', '/'), "[/]+", "/").TrimEnd('/'); //这里重复 path +=
}
} path = Regex.Replace(path.Replace('\\', '/'), "[/]+", "/").TrimEnd('/');
if (path.Length == 0)
path = "/"; /*if (!path.StartsWith("/") || !path.StartsWith("./"))
path = "./" + path;*/ return path;
}

  

 

csharp: FTP Client Library using System.Net.FtpClient and FluentFTP,测试中存在的BUG修正的更多相关文章

  1. csharp: FTP Client Library using System.Net.FtpWebRequest

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.D ...

  2. csharp:FTP Client Library using FtpWebRequest or Sockets

    https://netftp.codeplex.com/SourceControl/latest http://ftplib.codeplex.com/ https://www.codeproject ...

  3. 【FTP】C# System.Net.FtpClient库连接ftp服务器(上传文件)

    如果自己单枪匹马写一个连接ftp服务器代码那是相当恐怖的(socket通信),有一个评价较高的dll库可以供我们使用. 那就是System.Net.FtpClient,链接地址:https://net ...

  4. 【FTP】C# System.Net.FtpClient库连接ftp服务器(下载文件)

    如果自己单枪匹马写一个连接ftp服务器代码那是相当恐怖的(socket通信),有一个评价较高的dll库可以供我们使用. 那就是System.Net.FtpClient,链接地址:https://net ...

  5. System.Net.FtpClient改进

    项目用到Ftp,搜了下现有的类库System.Net.FtpClient 貌似比较不错. 一开始用着还行,但是有个FtpServer下有8k多内容,列表需要很久(7.8s)才能刷新出来. 翻源码吧,有 ...

  6. Memcached通用类(基于Memcached Client Library)

    分享下自己编写的Memcached通用类.欢迎大家帮忙指点下哈~ 使用的是.NET memcached client library 客户端+Memcached Providers using Sys ...

  7. 分布式缓存系统Memcached简介与实践(.NET memcached client library)

    缘起: 在数据驱动的web开发中,经常要重复从数据库中取出相同的数据,这种重复极大的增加了数据库负载.缓存是解决这个问题的好办法.但是ASP.NET中的虽然已经可以实现对页面局部进行缓存,但还是不够灵 ...

  8. Azure Storage Client Library 重试策略建议

    有关如何配置 Azure Storage Library 重试策略的信息,可参阅 Gaurav Mantri 撰写的一篇不错的文章<SCL 2.0 – 实施重试策略>.但很难找到关于使用何 ...

  9. Intro to Jedis – the Java Redis Client Library

    转自:http://www.baeldung.com/jedis-java-redis-client-library 1. Overview This article is an introducti ...

随机推荐

  1. 为什么需要micro-service构建平台

    最近一直在做micro-service的开发平台建设.由于这是一个实验项目,目前所有工作都得靠自己操刀. 今天在总结用python开发一个web service时,偶有所得,这让我建设micro-se ...

  2. 833. Find And Replace in String

    To some string S, we will perform some replacement operations that replace groups of letters with ne ...

  3. 770. Basic Calculator IV

    Given an expression such as expression = "e + 8 - a + 5" and an evaluation map such as {&q ...

  4. SpringDataSolr 过滤(或者叫筛选)查询

    // 被本类调用 private Map searchList(Map searchMap) { // 1.1关键字查询 SimpleHighlightQuery highlightQuery = n ...

  5. 转载 Python 正则表达式入门(中级篇)

    Python 正则表达式入门(中级篇) 初级篇链接:http://www.cnblogs.com/chuxiuhong/p/5885073.html 上一篇我们说在这一篇里,我们会介绍子表达式,向前向 ...

  6. oracle中常用的对用户的操作

    创建用户:create user usr1 identified by pwd default tablespace ts1 temporary tablespace tmp; 删除用户:drop u ...

  7. mysql 开发进阶篇系列 39 mysql日志之二进制日志(binlog)

    一.概述 二进制日志(binlog)记录了所有的DDL(数据定义语言)语句和DML(数据操纵语言)语句,但是不包括数据查询语句, 语句以"事件"的形式保存,它描述了数据的更改过程, ...

  8. SaltStack数据系统-Grans详解

    1:Grains是系统的一个组件,存放着minion启动时收集的系统底层的一些信息,每次minion启动的时候,会进行系统的采集,将其保存下来,在以后的生命周期中不会重新搜集,除非重启~ #查看gra ...

  9. Deep learning with Python 学习笔记(8)

    Keras 函数式编程 利用 Keras 函数式 API,你可以构建类图(graph-like)模型.在不同的输入之间共享某一层,并且还可以像使用 Python 函数一样使用 Keras 模型.Ker ...

  10. Tomcat8源码笔记(三)Catalina加载过程

    之前介绍过 Catalina加载过程是Bootstrap的load调用的  Tomcat8源码笔记(二)Bootstrap启动 按照Catalina的load过程,大致如下: 接下来一步步分析加载过程 ...