使用 C# 和 TcpComm 进行远程文件系统查看和文件传输
了解如何使用您自己的类似资源管理器的窗口,并使用 C# 和 TcpComm TCP 库通过拖放来传输文件和文件夹,从而查看远程计算机的文件系统。
引言
这是一个通过 TCP 传输文件和文件夹的完整示例,使用 C# 中的类似资源管理器的窗口,如上所示。使用示例应用程序,您可以通过在资源管理器中选择文件或文件夹并将它们拖到传输窗口的右窗格中,或者在传输窗口的右窗格中选择它们并将它们拖到资源管理器窗口来传输文件或文件夹。
我们这里拥有非常快速的类 FTP 功能,且没有大多数 FTP 客户端通常带来的麻烦。许多客户端不提供拖放功能,而是迫使您处理一个感觉过时的界面,该界面有一个单独的窗口显示本地和远程计算机文件系统的内容。
以这个示例为指导,您将能够使用 此处的 TcpComm
库,快速地将文件和文件夹传输功能集成到您的网络应用程序中。
尽管我在此示例项目中使用了 TcpComm
库,但您不必局限于它。我将 RemoteFileSystem
类(负责与远程计算机通信并获取文件系统信息的类)设计成了一个完整且独立的实体,可以与任何网络通信库一起使用。因此,如果您有更熟悉的网络库,或者想编写自己的库,您不必将 TcpComm
从此项目中移除并强行加入您的库,只需将 RemoteFileSystem
类放入您的项目中即可。
背景
我于 2012 年在此 CodeProject 上编写并发布了 TcpComm
库。多年来,人们一直问我如何传输文件夹。该库在客户端和服务器类中都提供了 GetFile()
和 SendFile()
函数……我还提供了一种更改客户端和服务器用于接收传入文件的文件夹的方法。因此,当被问到时,大多数时候我只是告诉人们他们需要自己将文件夹传输功能构建到他们的应用程序中。我会说我已经提供了工具,其余的就取决于您了。
最近,我正在开发的一个应用程序要求我做 exactly 同样的事情——构建一个显示远程计算机文件系统的 UI,并提供一种在本地和远程计算机之间传输文件的方式。我希望界面足够直观,因此那种笨拙的老式 Cute FTP 风格的界面,即为每个文件系统使用一个单独窗口的设计被淘汰了。我决定将此功能构建在一个单独的测试应用程序中,并在测试期间使用 TcpComm
库,以便我能够确保 TcpComm
中的文件传输代码尽可能紧凑,并最终为那些多年来一直询问的人提供如何传输文件夹的示例。
Using the Code
此应用程序的核心是 RemoteFileSystem
类。它拥有自己的客户端和服务器类,并负责处理有关远程文件系统的信息请求。RemoteFileSystem.Server
接受来自 RemoteFileSystem.Client
发送的 string
形式的请求。请求使用我构建的 XML 解析器 (XmlObject
) 格式化为 XML。
RFS (RemoteFileSystem
) 本身不通过网络发送任何数据,而是通过您选择的网络通信库通过委托传递每个请求或响应。在示例项目中,初始化 RFS 服务器所需的代码非常简短。
RFS 服务器构造函数如下所示
// Initialize RemoteFileSystem here:
rfsServer = new RemoteFileSystem.Server((String data) =>
{
// Send data to the client here:
UI(() => LblStatus.Text = "Sending data to client.");
lat.SendArray(TcpComm.Utilities.StrToByteArray(data), 100, currentSessionId, ref errMsg);
}, (String newPath) =>
{
// Handle requests to update the TcpComm server's received files folder here:
var session = tcpServer.GetSession(currentSessionId);
if (session != null) { session.ReceivedFilesFolder = newPath; }
});
相比之下,客户端构造函数相当冗长,因为服务器的回复数据正在被解析,并用于填充 Treeview
和 ListView
控件。
private void StartRFS()
{
rfsClient = new RemoteFileSystem.Client((String data) =>
{
// Requests are sent to the server here:
String errMsg = "";
if(!tcpClient.SendText(data, 100, ref errMsg))
{
MessageBox.Show("Could not send data to the server!",
"TCP Communications problem", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}, (RemoteFileSystem.Client.ServerReplyData serverData) =>
{
// Handle server replies here:
if (serverData.type.Equals("getdrives"))
{
// This code needs to be run on the UI thread:
UI(() =>
{
tvPaths.Nodes.Clear();
tvPaths.Nodes.Add("", remoteMachineName, 3);
TreeNode firstNode = tvPaths.Nodes[0];
...
此项目有大量的注释。我的意图是让有兴趣的各方阅读示例项目,以便他们能够掌握如何使用这些不同的组件。
关注点
- 在测试此项目时,如果您决定在单独的网络机器上测试服务器,请确保通过右键单击并以管理员身份运行来启动服务器。否则,服务器应用程序将无法访问文件系统,并在您第一次连接到它时悄悄关闭。
- 当您尝试连接到在单独的机器上运行的服务器时,请确保在连接字符串中指定端口,方法是将 IP 地址或主机名用冒号分隔,例如:your_IP_address_or_hostname:22490
- 此示例项目包含
XmlObject
的副本——一个我编写的 XML 解析器。它建立在XmlReader
之上,所以不,我并没有试图做什么突破性的事情。我只是想封装我最可能使用的功能,并使其以我认为我们都最习惯的方式使用。例如,当我看到 XML 时,我看到的是一组嵌套的对象。因此,当我的解析器访问 XML 时,我不想遍历节点,也不想处理非法字符。我只想像其他 OO 程序员一样,简单地访问我的对象,并轻松访问它的子对象。 - 此项目还包含几个辅助类。其中一个是
CopyFile
辅助类。它完成了传输文件和显示进度的所有繁重工作。 - 另一个是
DragDrop
辅助类。它提供了获取用户正在拖放到的 Windows 资源管理器文件夹名称的能力,因为 Windows 本身不提供此功能。此类中的大部分代码最初是在 此处找到的。
然而,我已采用 Joy 先生的示例并将其完全重写为一个简单的辅助类,而不是一个跨项目的大型示例。我还对其进行了改进,因此您永远不会看到被拖放的文件,即使它被拖放到桌面。
最后,我在 Windows 7、Windows 10 和 Windows Server 2012 中测试了此应用程序。在所有这些操作系统中,它都能正常工作。如果您发现它在 Windows 8 或 Windows XP 中无法正常工作,请随时在下方告知我。
历史
- 2017 年 5 月 2 日:初始版本