csharp: FTP Client Library using System.Net.FtpClient and FluentFTP,测试中存在的BUG修正
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修正的更多相关文章
- csharp: FTP Client Library using System.Net.FtpWebRequest
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.D ...
- csharp:FTP Client Library using FtpWebRequest or Sockets
https://netftp.codeplex.com/SourceControl/latest http://ftplib.codeplex.com/ https://www.codeproject ...
- 【FTP】C# System.Net.FtpClient库连接ftp服务器(上传文件)
如果自己单枪匹马写一个连接ftp服务器代码那是相当恐怖的(socket通信),有一个评价较高的dll库可以供我们使用. 那就是System.Net.FtpClient,链接地址:https://net ...
- 【FTP】C# System.Net.FtpClient库连接ftp服务器(下载文件)
如果自己单枪匹马写一个连接ftp服务器代码那是相当恐怖的(socket通信),有一个评价较高的dll库可以供我们使用. 那就是System.Net.FtpClient,链接地址:https://net ...
- System.Net.FtpClient改进
项目用到Ftp,搜了下现有的类库System.Net.FtpClient 貌似比较不错. 一开始用着还行,但是有个FtpServer下有8k多内容,列表需要很久(7.8s)才能刷新出来. 翻源码吧,有 ...
- Memcached通用类(基于Memcached Client Library)
分享下自己编写的Memcached通用类.欢迎大家帮忙指点下哈~ 使用的是.NET memcached client library 客户端+Memcached Providers using Sys ...
- 分布式缓存系统Memcached简介与实践(.NET memcached client library)
缘起: 在数据驱动的web开发中,经常要重复从数据库中取出相同的数据,这种重复极大的增加了数据库负载.缓存是解决这个问题的好办法.但是ASP.NET中的虽然已经可以实现对页面局部进行缓存,但还是不够灵 ...
- Azure Storage Client Library 重试策略建议
有关如何配置 Azure Storage Library 重试策略的信息,可参阅 Gaurav Mantri 撰写的一篇不错的文章<SCL 2.0 – 实施重试策略>.但很难找到关于使用何 ...
- Intro to Jedis – the Java Redis Client Library
转自:http://www.baeldung.com/jedis-java-redis-client-library 1. Overview This article is an introducti ...
随机推荐
- 为什么需要micro-service构建平台
最近一直在做micro-service的开发平台建设.由于这是一个实验项目,目前所有工作都得靠自己操刀. 今天在总结用python开发一个web service时,偶有所得,这让我建设micro-se ...
- 833. Find And Replace in String
To some string S, we will perform some replacement operations that replace groups of letters with ne ...
- 770. Basic Calculator IV
Given an expression such as expression = "e + 8 - a + 5" and an evaluation map such as {&q ...
- SpringDataSolr 过滤(或者叫筛选)查询
// 被本类调用 private Map searchList(Map searchMap) { // 1.1关键字查询 SimpleHighlightQuery highlightQuery = n ...
- 转载 Python 正则表达式入门(中级篇)
Python 正则表达式入门(中级篇) 初级篇链接:http://www.cnblogs.com/chuxiuhong/p/5885073.html 上一篇我们说在这一篇里,我们会介绍子表达式,向前向 ...
- oracle中常用的对用户的操作
创建用户:create user usr1 identified by pwd default tablespace ts1 temporary tablespace tmp; 删除用户:drop u ...
- mysql 开发进阶篇系列 39 mysql日志之二进制日志(binlog)
一.概述 二进制日志(binlog)记录了所有的DDL(数据定义语言)语句和DML(数据操纵语言)语句,但是不包括数据查询语句, 语句以"事件"的形式保存,它描述了数据的更改过程, ...
- SaltStack数据系统-Grans详解
1:Grains是系统的一个组件,存放着minion启动时收集的系统底层的一些信息,每次minion启动的时候,会进行系统的采集,将其保存下来,在以后的生命周期中不会重新搜集,除非重启~ #查看gra ...
- Deep learning with Python 学习笔记(8)
Keras 函数式编程 利用 Keras 函数式 API,你可以构建类图(graph-like)模型.在不同的输入之间共享某一层,并且还可以像使用 Python 函数一样使用 Keras 模型.Ker ...
- Tomcat8源码笔记(三)Catalina加载过程
之前介绍过 Catalina加载过程是Bootstrap的load调用的 Tomcat8源码笔记(二)Bootstrap启动 按照Catalina的load过程,大致如下: 接下来一步步分析加载过程 ...