FTP 的 OpenFileDialog
用于选择 FTP 服务器上文件的对话框。
引言
我不知道这个对话框是否对其他人有用,但我正在开发一个用于与网站交互、编辑等的应用程序,并且我需要在应用程序中有一个文本框,其中包含资源的链接。起初,我只是让用户自己正确输入资源 URL,但后来我想到,能够浏览到资源、选择它,然后根据所选文件自动填充文本框中的链接会很方便。这个对话框实现了这一点。
使用代码
对话框有两个可用的构造函数
FtpBrowseDialog();
FtpBrowseDialog(String host, String startpath, int port, String username, String password, bool passivemode);
基础构造函数将打开对话框,并弹出一个嵌套对话框提示输入连接变量。
- 服务器(主机)- 输入域名,不带“ftp://”,对话框会自动添加。
- 起始路径(可选)- 控制对话框开始的子目录。
- 端口 - 要使用的 TCP 端口,默认 FTP 端口是 21。
- 用户名 - 连接的用户名。
- 密码 - 连接的密码。
- 使用被动模式复选框 - 控制是否使用被动 FTP 连接,默认勾选为是。
另一个构造函数允许您传递所有这些变量,从而抑制连接提示。
连接后,将显示另一个子对话框,其中包含一个滚动进度条,用于在加载 FTP 文件结构时显示进度。加载完成后,进度对话框将关闭,即可访问文件结构。
如果您想在不加载服务器的情况下查看 UI 的工作方式,可以使用 TestMode
属性。在调用 ShowDialog()
之前将其设置为 true
,将加载一个模拟文件结构,供您用于测试目的。
这是 UI 的基本工作方式。我尽量模仿 OpenFileDialog
,但肯定还有一些功能缺失;欢迎提出未来版本改进的建议。
- 选择左侧的文件夹将填充该文件夹的子文件夹和文件在右侧。
- 在右侧面板中实际选择了一个文件之前,“确定”按钮将保持禁用状态。
- 提供了两个工具栏按钮
- 左侧的按钮向上移动一个目录,并在到达根文件夹时禁用。
- 右侧的按钮允许您打开一个新的服务器结构,将显示连接详细信息子对话框,默认使用当前的连接信息,但允许您输入新信息并点击“连接”以加载新服务器。
- 双击右侧面板中的文件将自动选择该文件并关闭对话框。
- 双击右侧面板中的子文件夹将导航到该文件夹。
- 当右侧面板获得焦点时,按退格键将模拟向上目录的工具栏按钮。
双击文件或按下“确定”按钮后,将返回 DialogResult.OK
,并且可以从调用窗体中收集文件信息。有三种选项可用于获取所选文件信息:
FtpBrowseDialog.SelectedFile
- 以包含 FTP 引用的 FQN 格式返回文件。FtpBrowseDialog.SelectedFileName
- 仅返回文件名。FtpBrowseDialog.SelectedFileUrl
- 以 Web 友好的格式返回文件,用于链接(注意:此方法还会将文件名中的所有空格替换为 %20)。
关注点(我的方法)
如果您是编程新手,您可能会问:“他是怎么做到的?!”而如果您是专业人士,您可能会想:“他**为什么**这么做?!”
这是项目的基础。首先,我创建了一个名为 FtpTreeNode
的新 TreeNode
类,并为其添加了一些额外的属性和方法。
FtpTreeNode.Files
- 一个StringCollection
,保存此节点表示的文件夹的所有文件名。FtpTreeNode.Directories
- 一个StringCollection
,保存此节点表示的文件夹的所有子目录名。
FtpTreeNode.AddFile(String file)
- 向集合中添加一个文件。FtpTreeNode.AddDirectory(String dir)
- 向集合中添加一个目录。FtpTreeNode.Select()
- 处理节点被选中时发生的细节。
通过在 FtpWebRequest
和 FtpWebResponse
之间进行协调来收集 FTP 信息。您可能在寻找如何控制 FtpWebRequest
的端口变量,而无需将其硬编码到连接字符串中使用“:”字符,以此找到了这里。答案很简单,但我花了一些时间才找到。使用 UriBuilder
实例可以实现此目的。使用 UriBuilder
,您需要提供协议类型“ftp”和主机域名,以及端口号和起始路径字符串。有几种不同的构造函数允许其中的一些细节成为可选。以下是用于填充对话框的 URI 示例。
UriBuilder ub = new UriBuilder("ftp", host, port, startpath);
我不得不使用 startpath
,因为我希望只有根节点具有 FQN,而每个子节点只显示目录名。
我还需要弄清楚的另一件事是,FtpWebRequest
有一个 UsePassive
属性,它控制是否使用 PASV 连接。旧服务器不使用被动模式,但大多数新服务器都使用。此外,您可以通过设置 FtpWebRequest
的 Credential
属性来控制用户名和密码。
FtpWebRequest req = new FtpWebRequest(ub.Uri);
req.Credential = new NetworkCredential(username, password);
bool passivemode = true; //Set to true or false based on your needs
req.UsePassive = passivemode;
现在到了有趣的部分。我必须使用方法递归来完成文件结构的加载。FtpBrowseDialog
中有一个名为 LoadSubNodes
的方法。
private void LoadSubNodes(FtpTreeNode node)
此方法将 request.Method
设置为 WebRequestMethods.Ftp.ListDirectroyDetails
,根据提供的节点的 FTP URL 获取响应,然后解析响应以将所有目录和文件添加到该节点,接着为每个目录创建一个子节点并将其传回 LoadSubNodes
,这就是递归的来源。一旦所有子目录节点都已加载并添加到此节点的子节点中,该方法就会返回。要启动此过程,只需创建一个根节点并将其传递给 LoadSubNodes
;在它返回后,将根节点添加到 TreeView
。
历史
- 2008 年 10 月 2 日 - v1.0 - 首次发布。
下一个版本计划
- 允许禁用“打开新服务器”按钮,从而可以将用户锁定到指定服务器。
- 更轻松地为文件列表面板添加不同文件类型的自定义图像。
- 提供文件过滤器属性,允许您控制对话框支持的文件类型。