FTP作为日常工作学习中,非常重要的一个文件传输存储空间,想必大家都非常的熟悉了,那么如何快速的实现文件的上传下载功能呢,本文以一个简单的小例子,简述如何通过FluentFTP实现文件的上传和下载功能。仅供学习分享使用,如有不足之处,还请指正。
FTP基础知识
文件传输协议(File Transfer Protocol,FTP)是用于在网络上进行文件传输的一套标准协议,它工作在 OSI 模型的第七层, TCP 模型的第四层, 即应用层, 使用 TCP 传输而不是 UDP, 客户在和服务器建立连接前要经过一个“三次握手”的过程, 保证客户与服务器之间的连接是可靠的, 而且是面向连接, 为数据传输提供可靠保证。FTP允许用户以文件操作的方式(如文件的增、删、改、查、传送等)与另一主机相互通信。然而, 用户并不真正登录到自己想要存取的计算机上面而成为完全用户, 可用FTP程序访问远程资源, 实现用户往返传输文件、目录管理以及访问电子邮件等等, 即使双方计算机可能配有不同的操作系统和文件存储方式。
FTP环境搭建
在windows操作系统中,FTP可以通过(Internet Inforamtion Services, IIS)管理器进行创建,创建成功后即可进行查看,如下所示:
FluentFTP安装
FluentFTP是一款基于.Net的FTP和FTPS的客户端动态库,操作简单便捷。
首先创建基于.Net Framework 4.6.1的winform应用程序,然后通过Nuget包管理器进行安装,如下所示:
示例演示
主要实现基于FTP的上传,下载,浏览等功能,如下所示:
进入文件夹及右键下载,如下所示:
示例源码
FtpHelper类源码,封装了FTP文件的检索,上传,下载等功能,如下所示:
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 using FluentFTP; 10 11 namespace DemoFtp 12 { 13 public class FtpHelper 14 { 15 #region 属性与构造函数 16 17 /// <summary> 18 /// IP地址 19 /// </summary> 20 public string IpAddr { get; set; } 21 22 /// <summary> 23 /// 相对路径 24 /// </summary> 25 public string RelatePath { get; set; } 26 27 /// <summary> 28 /// 端口号 29 /// </summary> 30 public int Port { get; set; } 31 32 /// <summary> 33 /// 用户名 34 /// </summary> 35 public string UserName { get; set; } 36 37 /// <summary> 38 /// 密码 39 /// </summary> 40 public string Password { get; set; } 41 42 public FtpHelper() 43 { 44 45 } 46 47 public FtpHelper(string ipAddr, int port, string userName, string password, string relatePath) 48 { 49 this.IpAddr = ipAddr; 50 this.Port = port; 51 this.UserName = userName; 52 this.Password = password; 53 this.RelatePath = relatePath; 54 } 55 56 #endregion 57 58 #region 方法 59 60 public FtpListItem[] ListDir() { 61 FtpListItem[] lists; 62 using (var ftpClient = new FtpClient(this.IpAddr, this.UserName, this.Password, this.Port)) 63 { 64 ftpClient.Connect(); 65 ftpClient.SetWorkingDirectory(this.RelatePath); 66 lists = ftpClient.GetListing(); 67 } 68 return lists; 69 } 70 71 public void UpLoad(string dir, string file, out bool isOk) 72 { 73 isOk = false; 74 FileInfo fi = new FileInfo(file); 75 using (FileStream fs = fi.OpenRead()) 76 { 77 //long length = fs.Length; 78 using (var ftpClient = new FtpClient(this.IpAddr, this.UserName, this.Password, this.Port)) 79 { 80 ftpClient.Connect(); 81 ftpClient.SetWorkingDirectory(this.RelatePath); 82 string remotePath = dir + "/" + Path.GetFileName(file); 83 var ftpRemodeExistsMode = file.EndsWith(".txt") ? FtpRemoteExists.Overwrite : FtpRemoteExists.Skip; 84 FtpStatus status = ftpClient.UploadStream(fs, remotePath, ftpRemodeExistsMode, true); 85 isOk = status == FtpStatus.Success; 86 87 } 88 } 89 90 } 91 92 /// <summary> 93 /// 上传多个文件 94 /// </summary> 95 /// <param name="files"></param> 96 /// <param name="isOk"></param> 97 public void UpLoad(string dir, string[] files, out bool isOk) 98 { 99 isOk = false; 100 if (CheckDirIsExists(dir)) 101 { 102 foreach (var file in files) 103 { 104 UpLoad(dir, file, out isOk); 105 } 106 } 107 } 108 109 110 private bool CheckDirIsExists(string dir) 111 { 112 bool flag = false; 113 using (var ftpClient = new FtpClient(this.IpAddr, this.UserName, this.Password, this.Port)) 114 { 115 ftpClient.Connect(); 116 ftpClient.SetWorkingDirectory(this.RelatePath); 117 flag = ftpClient.DirectoryExists(dir); 118 if (!flag) 119 { 120 flag = ftpClient.CreateDirectory(dir); 121 } 122 } 123 return flag; 124 125 126 } 127 128 /// <summary> 129 /// 下载ftp 130 /// </summary> 131 /// <param name="localAddress"></param> 132 /// <param name="remoteAddress"></param> 133 /// <returns></returns> 134 public bool DownloadFile(string localAddress, string remoteAddress) 135 { 136 using (var ftpClient = new FtpClient(this.IpAddr, this.UserName, this.Password, this.Port)) 137 { 138 ftpClient.SetWorkingDirectory("/"); 139 ftpClient.Connect(); 140 if (ftpClient.DownloadFile(localAddress, remoteAddress) == FtpStatus.Success) 141 { 142 return true; 143 } 144 return false; 145 } 146 } 147 148 #endregion 149 } 150 }
每一个FTP文件或文件夹,由一个自定义用户控件【PictureBox+Label+ContextMenu】表示,这样便于处理与显示:
1 using DemoFtp.Properties; 2 using FluentFTP; 3 using System; 4 using System.Collections.Generic; 5 using System.ComponentModel; 6 using System.Data; 7 using System.Drawing; 8 using System.IO; 9 using System.Linq; 10 using System.Text; 11 using System.Threading.Tasks; 12 using System.Windows.Forms; 13 14 namespace DemoFtp 15 { 16 public partial class FtpElementControl : UserControl 17 { 18 public Action<FtpListItem> SubFolderClick; 19 20 public Action<FtpListItem> DownLoadClick; 21 22 private FtpListItem ftpListItem; 23 24 public FtpElementControl(FtpListItem ftpListItem) 25 { 26 InitializeComponent(); 27 this.ftpListItem = ftpListItem; 28 } 29 30 public FtpElementControl() 31 { 32 InitializeComponent(); 33 } 34 35 public void InitControl() 36 { 37 if (ftpListItem.Type == FtpObjectType.Directory) 38 { 39 this.pbIcon.Image = Resources.folder.ToBitmap(); 40 } 41 else if (ftpListItem.Type == FtpObjectType.File) 42 { 43 var name = ftpListItem.Name; 44 var ext = Path.GetExtension(name).ToLower().Substring(1); 45 if (ext == "png" || ext == "jpeg" || ext == "jpg" || ext == "bmp" || ext == "gif") 46 { 47 this.pbIcon.Image = Resources.pictures.ToBitmap(); 48 } 49 else if (ext == "doc" || ext == "docx") 50 { 51 this.pbIcon.Image = Resources.doc.ToBitmap(); 52 } 53 else if (ext == "exe") 54 { 55 this.pbIcon.Image = Resources.setup.ToBitmap(); 56 } 57 else 58 { 59 this.pbIcon.Image = Resources.file; 60 } 61 } 62 else 63 { 64 this.pbIcon.Image = Resources.file; 65 } 66 this.lblName.Text = ftpListItem.Name; 67 } 68 69 private void FtpElementControl_Load(object sender, EventArgs e) 70 { 71 72 } 73 74 /// <summary> 75 /// 子菜单下载功能 76 /// </summary> 77 /// <param name="sender"></param> 78 /// <param name="e"></param> 79 private void menu_ItemClicked(object sender, ToolStripItemClickedEventArgs e) 80 { 81 this.DownLoadClick?.Invoke(ftpListItem); 82 } 83 84 /// <summary> 85 /// 双击打开 86 /// </summary> 87 /// <param name="sender"></param> 88 /// <param name="e"></param> 89 private void pbIcon_DoubleClick(object sender, EventArgs e) 90 { 91 this.SubFolderClick?.Invoke(ftpListItem); 92 } 93 } 94 }
主页面由一系列用户操作框和按钮组成,完成对FTP的基本操作,如下所示:
1 using FluentFTP; 2 using System; 3 using System.Collections.Generic; 4 using System.ComponentModel; 5 using System.Data; 6 using System.Drawing; 7 using System.IO; 8 using System.Linq; 9 using System.Text; 10 using System.Threading.Tasks; 11 using System.Windows.Forms; 12 13 namespace DemoFtp 14 { 15 public partial class MainForm : Form 16 { 17 private FtpHelper ftpHelper; 18 19 public MainForm() 20 { 21 InitializeComponent(); 22 } 23 24 private void btnLogin_Click(object sender, EventArgs e) 25 { 26 var url = txtFtpUrl.Text; 27 var userName = txtUserName.Text; 28 var password = txtPassword.Text; 29 var port = txtPort.Text; 30 if (this.lblRelatePath.Text != "/") 31 { 32 this.lblRelatePath.Text = "/"; 33 } 34 var relatePath = this.lblRelatePath.Text; 35 if (string.IsNullOrEmpty(url) || string.IsNullOrEmpty(userName) || string.IsNullOrEmpty(password) || string.IsNullOrEmpty(port)) 36 { 37 MessageBox.Show("路径和账号密码不可为空"); 38 return; 39 } 40 if (ftpHelper == null) 41 { 42 ftpHelper = new FtpHelper(url, int.Parse(port), userName, password, relatePath); 43 44 } 45 ListDir(); 46 } 47 48 public void SubFolder(FtpListItem ftpListItem) 49 { 50 if (ftpListItem.Type == FtpObjectType.Directory) 51 { 52 var fullName = ftpListItem.FullName; 53 ftpHelper.RelatePath = fullName; 54 ListDir(); 55 this.lblRelatePath.Text = fullName; 56 } 57 } 58 59 60 private void Download(FtpListItem ftpListItem) { 61 var fullName=ftpListItem.FullName; 62 var fileName = Path.GetFileName(fullName); 63 SaveFileDialog sfd = new SaveFileDialog(); 64 sfd.FileName = fileName; 65 sfd.Title = "不载"; 66 sfd.Filter = "所有文档|*.*"; 67 if (DialogResult.OK == sfd.ShowDialog()) { 68 ftpHelper.DownloadFile(sfd.FileName, fullName); 69 } 70 } 71 72 private void ListDir() 73 { 74 this.ftpContainer.Controls.Clear(); 75 var ftpListItems = this.ftpHelper.ListDir(); 76 if (ftpListItems != null && ftpListItems.Length > 0) 77 { 78 foreach (var ftpListItem in ftpListItems) 79 { 80 FtpElementControl ftpControl = new FtpElementControl(ftpListItem); 81 ftpControl.InitControl(); 82 ftpControl.DownLoadClick += Download; 83 ftpControl.SubFolderClick += SubFolder; 84 this.ftpContainer.Controls.Add(ftpControl); 85 } 86 } 87 } 88 89 private void btnUpload_Click(object sender, EventArgs e) 90 { 91 OpenFileDialog ofd = new OpenFileDialog(); 92 ofd.Filter = "所有文件|*.*"; 93 ofd.Title = "请选择需要上传的文件"; 94 if (DialogResult.OK == ofd.ShowDialog()) { 95 var localFile=ofd.FileName; 96 ftpHelper.UpLoad(this.lblRelatePath.Text, localFile, out bool isOk); 97 if (isOk) { 98 ListDir(); 99 } 100 } 101 } 102 103 private void pbReturn_Click(object sender, EventArgs e) 104 { 105 var relativePath=this.lblRelatePath.Text; 106 if (relativePath == "/") { 107 return; 108 } 109 relativePath = relativePath.Substring(0, relativePath.LastIndexOf("/")+1); 110 ftpHelper.RelatePath=relativePath; 111 ListDir(); 112 this.lblRelatePath.Text = relativePath; 113 } 114 } 115 }
以上就是基于FluentFTP实现FTP上传下载的全部内容,旨在抛砖引玉,共同学习,一起进步。