C# 实现FTP客户端
本文是利用C# 实现FTP客户端的小例子,主要实现上传,下载,删除等功能,以供学习分享使用。
思路:
- 通过读取FTP站点的目录信息,列出对应的文件及文件夹。
- 双击目录,则显示子目录,如果是文件,则点击右键,进行下载和删除操作。
- 通过读取本地电脑的目录,以树状结构展示,选择本地文件,右键进行上传操作。
涉及知识点:
- FtpWebRequest【实现文件传输协议 (FTP) 客户端】 / FtpWebResponse【封装文件传输协议 (FTP) 服务器对请求的响应】Ftp的操作主要集中在两个类中。
- FlowLayoutPanel 【流布局面板】表示一个沿水平或垂直方向动态排放其内容的面板。
- ContextMenuStrip 【快捷菜单】 主要用于右键菜单。
- 资源文件:Resources 用于存放图片及其他资源。
效果图如下
左边:双击文件夹进入子目录,点击工具栏按钮‘上级目录’返回。文件点击右键进行操作。
右边:文件夹则点击前面+号展开。文件则点击右键进行上传。
核心代码如下
1 using System; 2 using System.Collections.Generic; 3 using System.IO; 4 using System.Linq; 5 using System.Net; 6 using System.Text; 7 using System.Threading; 8 using System.Threading.Tasks; 9 10 namespace FtpClient 11 { 12 public class FtpHelper 13 { 14 #region 属性与构造函数 15 16 ///17 /// IP地址 18 /// 19 public string IpAddr { get; set; } 20 21 /// 22 /// 相对路径 23 /// 24 public string RelatePath { get; set; } 25 26 /// 27 /// 端口号 28 /// 29 public string Port { get; set; } 30 31 /// 32 /// 用户名 33 /// 34 public string UserName { get; set; } 35 36 /// 37 /// 密码 38 /// 39 public string Password { get; set; } 40 41 42 43 public FtpHelper() { 44 45 } 46 47 public FtpHelper(string ipAddr, string port, string userName, string password) { 48 this.IpAddr = ipAddr; 49 this.Port = port; 50 this.UserName = userName; 51 this.Password = password; 52 } 53 54 #endregion 55 56 #region 方法 57 58 59 /// 60 /// 下载文件 61 /// 62 /// 63 /// 64 public void DownLoad(string filePath, out bool isOk) { 65 string method = WebRequestMethods.Ftp.DownloadFile; 66 var statusCode = FtpStatusCode.DataAlreadyOpen; 67 FtpWebResponse response = callFtp(method); 68 ReadByBytes(filePath, response, statusCode, out isOk); 69 } 70 71 public void UpLoad(string file,out bool isOk) 72 { 73 isOk = false; 74 FileInfo fi = new FileInfo(file); 75 FileStream fs = fi.OpenRead(); 76 long length = fs.Length; 77 string uri = string.Format("ftp://{0}:{1}{2}", this.IpAddr, this.Port, this.RelatePath); 78 FtpWebRequest request = (FtpWebRequest)WebRequest.Create(uri); 79 request.Credentials = new NetworkCredential(UserName, Password); 80 request.Method = WebRequestMethods.Ftp.UploadFile; 81 request.UseBinary = true; 82 request.ContentLength = length; 83 request.Timeout = 10 * 1000; 84 try 85 { 86 Stream stream = request.GetRequestStream(); 87 88 int BufferLength = 2048; //2K 89 byte[] b = new byte[BufferLength]; 90 int i; 91 while ((i = fs.Read(b, 0, BufferLength)) > 0) 92 { 93 stream.Write(b, 0, i); 94 } 95 stream.Close(); 96 stream.Dispose(); 97 isOk = true; 98 } 99 catch (Exception ex) 100 { 101 Console.WriteLine(ex.ToString()); 102 } 103 finally { 104 if (request != null) 105 { 106 request.Abort(); 107 request = null; 108 } 109 } 110 } 111 112 /// 113 /// 删除文件 114 /// 115 /// 116 /// 117 public string[] DeleteFile(out bool isOk) { 118 string method = WebRequestMethods.Ftp.DeleteFile; 119 var statusCode = FtpStatusCode.FileActionOK; 120 FtpWebResponse response = callFtp(method); 121 return ReadByLine(response, statusCode, out isOk); 122 } 123 124 /// 125 /// 展示目录 126 /// 127 public string[] ListDirectory(out bool isOk) 128 { 129 string method = WebRequestMethods.Ftp.ListDirectoryDetails; 130 var statusCode = FtpStatusCode.DataAlreadyOpen; 131 FtpWebResponse response= callFtp(method); 132 return ReadByLine(response, statusCode, out isOk); 133 } 134 135 /// 136 /// 设置上级目录 137 /// 138 public void SetPrePath() 139 { 140 string relatePath = this.RelatePath; 141 if (string.IsNullOrEmpty(relatePath) || relatePath.LastIndexOf("/") == 0 ) 142 { 143 relatePath = ""; 144 } 145 else { 146 relatePath = relatePath.Substring(0, relatePath.LastIndexOf("/")); 147 } 148 this.RelatePath = relatePath; 149 } 150 151 #endregion 152 153 #region 私有方法 154 155 /// 156 /// 调用Ftp,将命令发往Ftp并返回信息 157 /// 158 /// 要发往Ftp的命令 159 /// 160 private FtpWebResponse callFtp(string method) 161 { 162 string uri = string.Format("ftp://{0}:{1}{2}", this.IpAddr, this.Port, this.RelatePath); 163 FtpWebRequest request; request = (FtpWebRequest)FtpWebRequest.Create(uri); 164 request.UseBinary = true; 165 request.UsePassive = true; 166 request.Credentials = new NetworkCredential(UserName, Password); 167 request.KeepAlive = false; 168 request.Method = method; 169 FtpWebResponse response = (FtpWebResponse)request.GetResponse(); 170 return response; 171 } 172 173 /// 174 /// 按行读取 175 /// 176 /// 177 /// 178 /// 179 /// 180 private string[] ReadByLine(FtpWebResponse response, FtpStatusCode statusCode,out bool isOk) { 181 List<string> lstAccpet = new List<string>(); 182 int i = 0; 183 while (true) 184 { 185 if (response.StatusCode == statusCode) 186 { 187 using (StreamReader sr = new StreamReader(response.GetResponseStream())) 188 { 189 string line = sr.ReadLine(); 190 while (!string.IsNullOrEmpty(line)) 191 { 192 lstAccpet.Add(line); 193 line = sr.ReadLine(); 194 } 195 } 196 isOk = true; 197 break; 198 } 199 i++; 200 if (i > 10) 201 { 202 isOk = false; 203 break; 204 } 205 Thread.Sleep(200); 206 } 207 response.Close(); 208 return lstAccpet.ToArray(); 209 } 210 211 private void ReadByBytes(string filePath,FtpWebResponse response, FtpStatusCode statusCode, out bool isOk) 212 { 213 isOk = false; 214 int i = 0; 215 while (true) 216 217 { 218 if (response.StatusCode == statusCode) 219 { 220 long length = response.ContentLength; 221 int bufferSize = 2048; 222 int readCount; 223 byte[] buffer = new byte[bufferSize]; 224 using (FileStream outputStream = new FileStream(filePath, FileMode.Create)) 225 { 226 227 using (Stream ftpStream = response.GetResponseStream()) 228 { 229 readCount = ftpStream.Read(buffer, 0, bufferSize); 230 while (readCount > 0) 231 { 232 outputStream.Write(buffer, 0, readCount); 233 readCount = ftpStream.Read(buffer, 0, bufferSize); 234 } 235 } 236 } 237 break; 238 } 239 i++; 240 if (i > 10) 241 { 242 isOk = false; 243 break; 244 } 245 Thread.Sleep(200); 246 } 247 response.Close(); 248 } 249 #endregion 250 } 251 252 /// 253 /// Ftp内容类型枚举 254 /// 255 public enum FtpContentType 256 { 257 undefined = 0, 258 file = 1, 259 folder = 2 260 } 261 }
FTP服务端和客户端示意图
---------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------
源码链接如下:
源码下载