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 ...
随机推荐
- Visual Stuido快捷键
转自:http://www.cnblogs.com/TankXiao/p/3164995.html 整理了一些VS的快捷键 格式化整个文档:(Ctrl + K, Ctrl + D)智能感知:(Ctrl ...
- jsapi微信支付
JSAPI微信支付 引用js <script type="text/javascript" src="http://res.wx.qq.com/open/js/jw ...
- git checkout tags with the same name as a branch
显式指定某个 tag git checkout refs/tags/ git checkout refs/tags/v0.1 显式指定某个 branch git checkout refs/heads ...
- APK防护——Anti_Virtual App的思路和实现
作者:HAI_i 原文来自:https://bbs.ichunqiu.com/thread-42982-1-1.html 0×00 前言 Virtual App是一个很强大的存在,破坏了Android ...
- FTPClient 中 FTPClient.changeWorkingDirectory(filePath) 代码一直返回 false
FTP文件下载需要的jar包: commons-net-2.0.jar 有时可能还需要:jakarta-oro.jar 参考:FTPClient参考文档 这里记录下我碰到的问题: 刚开始我的账号和密 ...
- [Swift]扩展UIColor:实现十六进制颜色字符串与UIColor之间的相互转换
对[UIColor]进行扩展 import UIKit extension UIColor { // Hex String -> UIColor convenience init(hexStri ...
- Shell-1--概念
- 数组的三种声明方式总结、多维数组的遍历、Arrays类的常用方法总结
1. 数组的三种声明方式 public class WhatEver { public static void main(String[] args) { //第一种 例: String[] test ...
- python 变量进阶(理解)
变量进阶(理解) 目标 变量的引用 可变和不可变类型 局部变量和全局变量 01. 变量的引用 变量 和 数据 都是保存在 内存 中的 在 Python 中 函数 的 参数传递 以及 返回值 都是靠 引 ...
- linux中一些简便的命令之wc
wc命令是统计文本中的字符数.单词数以及文本行数的,具体参数如下: -l 统计文本中的行数 -w 统计文本中的单词数 -c/m 统计文本中的字符数 -L 统计文本中最长行的字符数 当然使用时也可以不带 ...