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. [Python] networkx入门 转

    networkx是python的一个第三方包,可以方便地调用各种图算法的计算. 通过调用python画图包matplotlib能实现图的可视化. 1.安装 正好整理一下python第三方包的安装方法. ...

  2. MySQL基础--字符函数

    1.UPPER和UCASE返回字符串str,根据当前字符集映射(缺省是ISO-8859-1 Latin1)把所有的字符改变成大写.该函数对多字节是可靠的. 2.LOWER和LCASE返回字符串str, ...

  3. ZKWeb网页框架1.9正式发布

    1.9.0更新的内容有 更新项目工具 更好的支持Linux 添加工具函数 Exception.ToDetailedString (获取例外的详细信息) Exception.ToSummaryStrin ...

  4. 1,rocketmq 的原理与安装教程

    参考文档 http://blog.csdn.net/a19881029/article/details/34446629 https://github.com/alibaba/RocketMQ htt ...

  5. Python语法基础——关于全局变量与局部变量

    1.函数内部的变量名如果第一次出现,且出现在=前面,即被视为定义一个局部变量,不管全局域中有没有用到该变量名,函数中使用的将是局部变量,例如: num = 100 def func(): num =  ...

  6. Spring Boot Debug调试

    在使用spring-boot:run进行启动的时候,如果设置的断点进不去,要进行以下的设置. 1.添加jvm参数配置 在spring-boot的maven插件加上jvmArguments配置. < ...

  7. HTML编辑器 -- KindEditor

    KindEditor 是一套开源的在线HTML编辑器,主要用于让用户在网站上获得所见即所得编辑效果,开发人员可以用 KindEditor 把传统的多行文本输入框(textarea)替换为可视化的富文本 ...

  8. ArrayList源码解读笔记

    简介: ArrayList是我们开发中非常常用的数据存储容器之一,其底层是数组实现的,我们可以在集合中存储任意类型的数据,ArrayList是线程不安全的,非常适合用于对元素进行查找,效率非常高. 线 ...

  9. IDEA的maven配置

    刚接触maven的时候,也知道maven目录下有个setting文件可以设置远程maven库的地址,但自己实践的时候,发现setting文件的地址都被注释掉了,但是jar包还是能成功下载下来,那这个下 ...

  10. app自动化测试之实战应用(魅族计算器)

    模拟魅族计算器加法计算: from appium import webdriver desired_caps = {} desired_caps['deviceName'] = '621QECQ23D ...