前言
本篇主要记录:VS2019 WinFrm桌面应用程序实现简单的FtpClient,包含Ftp文件查看、上传和下载等功能。
准备工作
搭建WinFrm前台界面
添加必要的控件,这里主要应用到GroupBox、Label、TextBox和Button,如下图

核心代码
构造FtpHelper类
代码如下:

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.Tasks;
8
9 namespace FtpClientTest
10 {
11 public class FtpHelper
12 {
13 // FTP连接地址
14 string ftpServerIP;
15 // 指定FTP连接成功后的当前目录, 如果不指定即默认为根目录
16 string ftpRemotePath;
17 // 用户名
18 string ftpUserID;
19 // 密码
20 string ftpPassword;
21 // 通用处理路径
22 string ftpURI;
23
24 /// <summary>
25 /// 连接FTP
26 /// </summary>
27 /// <param name="FtpServerIP">FTP连接地址</param>
28 /// <param name="FtpRemotePath">指定FTP连接成功后的当前目录, 如果不指定即默认为根目录</param>
29 /// <param name="FtpUserID">用户名</param>
30 /// <param name="FtpPassword">密码</param>
31 public FtpHelper(string FtpServerIP, string FtpRemotePath, string FtpUserID, string FtpPassword)
32 {
33 ftpServerIP = FtpServerIP;
34 ftpRemotePath = FtpRemotePath;
35 ftpUserID = FtpUserID;
36 ftpPassword = FtpPassword;
37 ftpURI = "ftp://" + ftpServerIP + "/" + ftpRemotePath + "/";
38 }
39
40 /// <summary>
41 /// 上传
42 /// </summary>
43 /// <param name="filename">本地文件全路径</param>
44 public void Upload(string filename)
45 {
46 FileInfo fileInf = new FileInfo(filename);
47 string uri = ftpURI + fileInf.Name;
48 FtpWebRequest reqFTP;
49
50 reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri));
51 reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
52 reqFTP.KeepAlive = false;
53 reqFTP.Method = WebRequestMethods.Ftp.UploadFile;
54 reqFTP.UseBinary = true;
55 reqFTP.UsePassive = false;
56 reqFTP.ContentLength = fileInf.Length;
57 int buffLength = 2048;
58 byte[] buff = new byte[buffLength];
59 int contentLen;
60 FileStream fs = fileInf.OpenRead();
61 try
62 {
63 Stream strm = reqFTP.GetRequestStream();
64 contentLen = fs.Read(buff, 0, buffLength);
65 while (contentLen != 0)
66 {
67 strm.Write(buff, 0, contentLen);
68 contentLen = fs.Read(buff, 0, buffLength);
69 }
70 strm.Close();
71 fs.Close();
72 }
73 catch (Exception ex)
74 {
75 throw new Exception("Ftphelper Upload Error --> " + ex.Message);
76 }
77 }
78
79 /// <summary>
80 /// 下载
81 /// </summary>
82 /// <param name="filePath">文件保存本地路径</param>
83 /// <param name="fileName">Ftp上文件的路径</param>
84 public void Download(string filePath, string fileName)
85 {
86 FtpWebRequest reqFTP;
87 try
88 {
89 FileStream outputStream = new FileStream(filePath + "\\" + fileName, FileMode.Create);
90
91 reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(ftpURI + fileName));
92 reqFTP.Method = WebRequestMethods.Ftp.DownloadFile;
93 reqFTP.UseBinary = true;
94 reqFTP.UsePassive = false;
95 reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
96 FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
97 Stream ftpStream = response.GetResponseStream();
98 long cl = response.ContentLength;
99 int bufferSize = 2048;
100 int readCount;
101 byte[] buffer = new byte[bufferSize];
102
103 readCount = ftpStream.Read(buffer, 0, bufferSize);
104 while (readCount > 0)
105 {
106 outputStream.Write(buffer, 0, readCount);
107 readCount = ftpStream.Read(buffer, 0, bufferSize);
108 }
109
110 ftpStream.Close();
111 outputStream.Close();
112 response.Close();
113 }
114 catch (Exception ex)
115 {
116 throw new Exception("FtpHelper Download Error --> " + ex.Message);
117 }
118 }
119
120 /// <summary>
121 /// 删除文件
122 /// </summary>
123 /// <param name="fileName">Ftp上文件的名称</param>
124 public void Delete(string fileName)
125 {
126 try
127 {
128 string uri = ftpURI + fileName;
129 FtpWebRequest reqFTP;
130 reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri));
131
132 reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
133 reqFTP.KeepAlive = false;
134 reqFTP.Method = WebRequestMethods.Ftp.DeleteFile;
135 reqFTP.UsePassive = false;
136
137 string result = String.Empty;
138 FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
139 long size = response.ContentLength;
140 Stream datastream = response.GetResponseStream();
141 StreamReader sr = new StreamReader(datastream);
142 result = sr.ReadToEnd();
143 sr.Close();
144 datastream.Close();
145 response.Close();
146 }
147 catch (Exception ex)
148 {
149 throw new Exception("FtpHelper Delete Error --> " + ex.Message + " 文件名:" + fileName);
150 }
151 }
152
153 /// <summary>
154 /// 删除文件夹
155 /// </summary>
156 /// <param name="folderName">Ftp上文件夹的名称</param>
157 public void RemoveDirectory(string folderName)
158 {
159 try
160 {
161 string uri = ftpURI + folderName;
162 FtpWebRequest reqFTP;
163 reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri));
164
165 reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
166 reqFTP.KeepAlive = false;
167 reqFTP.Method = WebRequestMethods.Ftp.RemoveDirectory;
168 reqFTP.UsePassive = false;
169
170 string result = String.Empty;
171 FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
172 long size = response.ContentLength;
173 Stream datastream = response.GetResponseStream();
174 StreamReader sr = new StreamReader(datastream);
175 result = sr.ReadToEnd();
176 sr.Close();
177 datastream.Close();
178 response.Close();
179 }
180 catch (Exception ex)
181 {
182 throw new Exception("FtpHelper Delete Error --> " + ex.Message + " 文件名:" + folderName);
183 }
184 }
185
186 /// <summary>
187 /// 获取当前目录下明细(包含文件和文件夹)
188 /// </summary>
189 /// <returns></returns>
190 public string[] GetFilesDetailList()
191 {
192 string[] downloadFiles;
193 try
194 {
195 StringBuilder result = new StringBuilder();
196 FtpWebRequest ftp;
197 ftp = (FtpWebRequest)FtpWebRequest.Create(new Uri(ftpURI));
198 ftp.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
199 ftp.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
200 ftp.UsePassive = false;
201 WebResponse response = ftp.GetResponse();
202 StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.Default);
203
204 //while (reader.Read() > 0)
205 //{
206
207 //}
208 string line = reader.ReadLine();
209 //line = reader.ReadLine();
210 //line = reader.ReadLine();
211
212 while (line != null)
213 {
214 result.Append(line);
215 result.Append("\n");
216 line = reader.ReadLine();
217 }
218 result.Remove(result.ToString().LastIndexOf("\n"), 1);
219 reader.Close();
220 response.Close();
221 return result.ToString().Split('\n');
222 }
223 catch (Exception ex)
224 {
225 downloadFiles = null;
226 throw new Exception("FtpHelper Error --> " + ex.Message);
227 }
228 }
229
230 /// <summary>
231 /// 获取当前目录下文件列表(仅文件)
232 /// </summary>
233 /// <returns></returns>
234 public string[] GetFileList(string mask)
235 {
236 string[] downloadFiles;
237 StringBuilder result = new StringBuilder();
238 FtpWebRequest reqFTP;
239 try
240 {
241 reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(ftpURI));
242 reqFTP.UseBinary = true;
243 reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
244 reqFTP.Method = WebRequestMethods.Ftp.ListDirectory;
245 reqFTP.UsePassive = false;
246 WebResponse response = reqFTP.GetResponse();
247 StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.Default);
248
249 string line = reader.ReadLine();
250 while (line != null)
251 {
252 if (mask.Trim() != string.Empty && mask.Trim() != "*.*")
253 {
254
255 string mask_ = mask.Substring(0, mask.IndexOf("*"));
256 if (line.Substring(0, mask_.Length) == mask_)
257 {
258 result.Append(line);
259 result.Append("\n");
260 }
261 }
262 else
263 {
264 result.Append(line);
265 result.Append("\n");
266 }
267 line = reader.ReadLine();
268 }
269 result.Remove(result.ToString().LastIndexOf('\n'), 1);
270 reader.Close();
271 response.Close();
272 return result.ToString().Split('\n');
273 }
274 catch (Exception ex)
275 {
276 downloadFiles = null;
277 if (ex.Message.Trim() != "远程服务器返回错误: (550) 文件不可用(例如,未找到文件,无法访问文件)。")
278 {
279 throw new Exception("FtpHelper GetFileList Error --> " + ex.Message.ToString());
280 }
281 return downloadFiles;
282 }
283 }
284
285 /// <summary>
286 /// 获取当前目录下所有的文件夹列表(仅文件夹)
287 /// </summary>
288 /// <returns></returns>
289 public string[] GetDirectoryList()
290 {
291 string[] drectory = GetFilesDetailList();
292 string m = string.Empty;
293 foreach (string str in drectory)
294 {
295 int dirPos = str.IndexOf("<DIR>");
296 if (dirPos > 0)
297 {
298 /*判断 Windows 风格*/
299 m += str.Substring(dirPos + 5).Trim() + "\n";
300 }
301 else if (str.Trim().Substring(0, 1).ToUpper() == "D")
302 {
303 /*判断 Unix 风格*/
304 string dir = str.Substring(54).Trim();
305 if (dir != "." && dir != "..")
306 {
307 m += dir + "\n";
308 }
309 }
310 }
311
312 char[] n = new char[] { '\n' };
313 return m.Split(n);
314 }
315
316 /// <summary>
317 /// 判断当前目录下指定的子目录是否存在
318 /// </summary>
319 /// <param name="RemoteDirectoryName">指定的目录名</param>
320 public bool DirectoryExist(string RemoteDirectoryName)
321 {
322 string[] dirList = GetDirectoryList();
323 foreach (string str in dirList)
324 {
325 if (str.Trim() == RemoteDirectoryName.Trim())
326 {
327 return true;
328 }
329 }
330 return false;
331 }
332
333 /// <summary>
334 /// 判断当前目录下指定的文件是否存在
335 /// </summary>
336 /// <param name="RemoteFileName">远程文件名</param>
337 public bool FileExist(string RemoteFileName)
338 {
339 string[] fileList = GetFileList("*.*");
340 foreach (string str in fileList)
341 {
342 if (str.Trim() == RemoteFileName.Trim())
343 {
344 return true;
345 }
346 }
347 return false;
348 }
349
350 /// <summary>
351 /// 创建文件夹
352 /// </summary>
353 /// <param name="dirName"></param>
354 public void MakeDir(string dirName)
355 {
356 FtpWebRequest reqFTP;
357 try
358 {
359 // dirName = name of the directory to create.
360 reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(ftpURI + dirName));
361 reqFTP.Method = WebRequestMethods.Ftp.MakeDirectory;
362 reqFTP.UseBinary = true;
363 reqFTP.UsePassive = false;
364 reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
365 FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
366 Stream ftpStream = response.GetResponseStream();
367
368 ftpStream.Close();
369 response.Close();
370 }
371 catch (Exception ex)
372 {
373 throw new Exception("FtpHelper MakeDir Error --> " + ex.Message);
374 }
375 }
376
377 /// <summary>
378 /// 获取指定文件大小
379 /// </summary>
380 /// <param name="filename"></param>
381 /// <returns></returns>
382 public long GetFileSize(string filename)
383 {
384 FtpWebRequest reqFTP;
385 long fileSize = 0;
386 try
387 {
388 reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(ftpURI + filename));
389 reqFTP.Method = WebRequestMethods.Ftp.GetFileSize;
390 reqFTP.UseBinary = true;
391 reqFTP.UsePassive = false;
392 reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
393 FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
394 Stream ftpStream = response.GetResponseStream();
395 fileSize = response.ContentLength;
396
397 ftpStream.Close();
398 response.Close();
399 }
400 catch (Exception ex)
401 {
402 throw new Exception("FtpHelper GetFileSize Error --> " + ex.Message);
403 }
404 return fileSize;
405 }
406
407 /// <summary>
408 /// 改名
409 /// </summary>
410 /// <param name="currentFilename"></param>
411 /// <param name="newFilename"></param>
412 public void ReName(string currentFilename, string newFilename)
413 {
414 FtpWebRequest reqFTP;
415 try
416 {
417 reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(ftpURI + currentFilename));
418 reqFTP.Method = WebRequestMethods.Ftp.Rename;
419 reqFTP.RenameTo = newFilename;
420 reqFTP.UseBinary = true;
421 reqFTP.UsePassive = false;
422 reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
423 FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
424 Stream ftpStream = response.GetResponseStream();
425
426 ftpStream.Close();
427 response.Close();
428 }
429 catch (Exception ex)
430 {
431 throw new Exception("FtpHelper ReName Error --> " + ex.Message);
432 }
433 }
434
435 /// <summary>
436 /// 移动文件
437 /// </summary>
438 /// <param name="currentFilename"></param>
439 /// <param name="newFilename"></param>
440 public void MovieFile(string currentFilename, string newDirectory)
441 {
442 ReName(currentFilename, newDirectory);
443 }
444
445 /// <summary>
446 /// 切换当前目录
447 /// </summary>
448 /// <param name="DirectoryName"></param>
449 /// <param name="IsRoot">true 绝对路径 false 相对路径</param>
450 public void GotoDirectory(string DirectoryName, bool IsRoot)
451 {
452 if (IsRoot)
453 {
454 ftpRemotePath = DirectoryName;
455 }
456 else
457 {
458 ftpRemotePath += DirectoryName + "/";
459 }
460 ftpURI = "ftp://" + ftpServerIP + "/" + ftpRemotePath + "/";
461 }
462
463 /// <summary>
464 /// 删除订单目录
465 /// </summary>
466 /// <param name="ftpServerIP">FTP 主机地址</param>
467 /// <param name="folderToDelete">FTP 用户名</param>
468 /// <param name="ftpUserID">FTP 用户名</param>
469 /// <param name="ftpPassword">FTP 密码</param>
470 public static void DeleteOrderDirectory(string ftpServerIP, string folderToDelete, string ftpUserID, string ftpPassword)
471 {
472 try
473 {
474 if (!string.IsNullOrEmpty(ftpServerIP) && !string.IsNullOrEmpty(folderToDelete) && !string.IsNullOrEmpty(ftpUserID) && !string.IsNullOrEmpty(ftpPassword))
475 {
476 FtpHelper fw = new FtpHelper(ftpServerIP, folderToDelete, ftpUserID, ftpPassword);
477 //进入订单目录
478 fw.GotoDirectory(folderToDelete, true);
479 //获取规格目录
480 string[] folders = fw.GetDirectoryList();
481 foreach (string folder in folders)
482 {
483 if (!string.IsNullOrEmpty(folder) || folder != "")
484 {
485 //进入订单目录
486 string subFolder = folderToDelete + "/" + folder;
487 fw.GotoDirectory(subFolder, true);
488 //获取文件列表
489 string[] files = fw.GetFileList("*.*");
490 if (files != null)
491 {
492 //删除文件
493 foreach (string file in files)
494 {
495 fw.Delete(file);
496 }
497 }
498 //删除冲印规格文件夹
499 fw.GotoDirectory(folderToDelete, true);
500 fw.RemoveDirectory(folder);
501 }
502 }
503
504 //删除订单文件夹
505 string parentFolder = folderToDelete.Remove(folderToDelete.LastIndexOf('/'));
506 string orderFolder = folderToDelete.Substring(folderToDelete.LastIndexOf('/') + 1);
507 fw.GotoDirectory(parentFolder, true);
508 fw.RemoveDirectory(orderFolder);
509 }
510 else
511 {
512 throw new Exception("FTP 及路径不能为空!");
513 }
514 }
515 catch (Exception ex)
516 {
517 throw new Exception("删除订单时发生错误,错误信息为:" + ex.Message);
518 }
519 }
520 }
521 }
配合控件重写Ftp方法
代码如下:

1 using System;
2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.Data;
5 using System.Drawing;
6 using System.IO;
7 using System.Linq;
8 using System.Net;
9 using System.Text;
10 using System.Threading.Tasks;
11 using System.Windows.Forms;
12
13 namespace FtpClientTest
14 {
15 public partial class FrmMain : Form
16 {
17 public FrmMain()
18 {
19 InitializeComponent();
20 }
21
22 // 定义全局变量 ftp参数
23 private FtpHelper ftpHelper;
24 private string ipAddr;
25 private string port;
26 private string path;
27 private string userName;
28 private string password;
29
30 /// <summary>
31 /// 方法:Ftp初始化
32 /// </summary>
33 private void FtpInit()
34 {
35 ipAddr = this.txtHost.Text;
36 port = this.txtHost.Text;
37 path = this.txtCurrentDir.Text;
38 userName = this.txtUserName.Text;
39 password = this.txtPassCode.Text;
40 ftpHelper = new FtpHelper(ipAddr, path, userName, password);
41 }
42
43 /// <summary>
44 /// 事件:文件下载
45 /// </summary>
46 /// <param name="sender"></param>
47 /// <param name="e"></param>
48 private void btnDownLoad_Click(object sender, EventArgs e)
49 {
50 try
51 {
52 ftpHelper.Download(@"D:\", this.txtFilePath.Text.Trim());
53 MessageBox.Show("下载成功!", "提示");
54 }
55 catch (Exception ex)
56 {
57 MessageBox.Show("下载失败!错误信息[" + ex.Message + "]", "警告");
58 }
59
60 }
61 /// <summary>
62 /// 方法:获取Ftp当前目录下的文件
63 /// </summary>
64 private void GetFileList()
65 {
66 string[] str = ftpHelper.GetFilesDetailList();
67 tbFileLists.Text = "";
68 for (int i = 0; i < str.Length - 1; i++)
69 {
70 if (tbFileLists.Text.ToString() == "")
71 {
72 tbFileLists.Text = str[i];
73 }
74 else
75 {
76 tbFileLists.Text = tbFileLists.Text + "\r\n" + str[i];
77 }
78 }
79 }
80
81 /// <summary>
82 /// 事件:连接Ftp,获取文件列表
83 /// </summary>
84 /// <param name="sender"></param>
85 /// <param name="e"></param>
86 private void btnConnect_Click(object sender, EventArgs e)
87 {
88 try
89 {
90 FtpInit();
91 this.btnDownLoad.Enabled = true;
92 this.btnUpload.Enabled = true;
93 this.btnOpen.Enabled = true;
94 GetFileList();
95 }
96 catch (Exception ex)
97 {
98 this.btnDownLoad.Enabled = false;
99 this.btnUpload.Enabled = false;
100 this.btnOpen.Enabled = false;
101 MessageBox.Show("连接失败!错误信息[" + ex.Message + "]", "警告");
102 }
103 }
104
105 /// <summary>
106 /// 事件:上传文件
107 /// </summary>
108 /// <param name="sender"></param>
109 /// <param name="e"></param>
110 private void btnUpload_Click(object sender, EventArgs e)
111 {
112 try
113 {
114 ftpHelper.Upload(this.txtLocalFilePath.Text.Trim());
115 MessageBox.Show("上传成功!", "提示");
116 }
117 catch (Exception ex)
118 {
119 MessageBox.Show("上传失败!错误信息[" + ex.Message + "]", "警告");
120 }
121 }
122
123 /// <summary>
124 /// 事件:选中需要上传的文件
125 /// </summary>
126 /// <param name="sender"></param>
127 /// <param name="e"></param>
128 private void btnOpen_Click(object sender, EventArgs e)
129 {
130 // 创建 OpenFileDialog 对象
131 OpenFileDialog ofd = new OpenFileDialog();
132 // 设定默认打开文件类型,删选、设定文件显示类型
133 ofd.Filter = "(*.et;*.xls;*.xlsx)|*.et;*.xls;*.xlsx|all|*.*";
134 // 显示打开文件的窗口
135 ofd.ShowDialog();
136 // 获得选择的文件路径,并赋值给
137 this.txtLocalFilePath.Text = ofd.FileName;
138 }
139 }
140 }
实现效果

