csharp: FTP Client Library using System.Net.FtpClient and FluentFTP,測試中存在的BUG

来源:http://www.cnblogs.com/geovindu/archive/2017/08/02/7274642.html
-Advertisement-
Play Games

https://netftp.codeplex.com/ 測試 https://github.com/hgupta9/FluentFTP ...


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;
		}

  

 

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1、與用戶(user)和用戶組(group)相關的配置文件; 1)與用戶(user)相關的配置文件;/etc/passwd 註:用戶(user)的配置文件;/etc/shadow 註:用戶(user)影子口令文件; 2)與用戶組(group)相關的配置文件;/etc/group 註:用戶組(grou ...
  • 幾天前,我和我的朋友們使用 ASP.NET Core 開發了一個API ,使用的是GET方式,將一些數據返回到客戶端 APP。我們在前端進行了分頁,意味著我們將所有數據發送給客戶端,然後進行一些data.length操作,以獲得items count用於分頁邏輯。為了減少HTTP請求的負荷,我們決定 ...
  • 首先,添加一個類AuthenticationAttribute,該類繼承AuthorizeAttribute,如下: using System.Web; using System.Web.Mvc; namespace Zhong.Web { public class AuthenticationAt ...
  • 效果 實現思路 使用TcpListener建一個伺服器,接收所有客戶端發送的消息,然後由伺服器再發送到其他客戶端 客戶端使用TcpClient,發消息給伺服器,接收伺服器的消息,不和其他客戶端直接交互 伺服器端 開啟一個線程,死迴圈去接收客戶端.接收到之後放到一個集合里,保存起來,以便轉發消息用.每 ...
  • 上文簡單介紹了一下Entity FrameWork,這裡說一下EF的核心——edmx文件。 在VisualStudio中建立edmx文件(此例環境為VisualStudio2012) 1、新建—ADO.NET實體數據模型: 2、選擇數據模型時,因為我之前已經在資料庫中建立好表了,所以我們這裡先選擇從 ...
  • Entity Framework是以ADO.NET為基礎,面向數據的“實體框架”。以下簡稱EF。 它利用了抽象化數據結構的方式,將每個資料庫對象都轉換成應用程式對象 (entity),數據欄位都轉換為屬性 (property),關係則轉換為結合屬性 (association),讓資料庫的 E/R 模 ...
  • 測試代碼: ...
  • 下載地址為:http://npoi.codeplex.com/releases/view/616131 可以操作excel表,行,單元格內家及樣式等。 使用示例: using (FileStream fs = File.OpenRead(@"E:\a.xls")) //打開myxls.xls文件 { ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...