Introduction
This is a complete example of how to transfer files and folders over TCP, by using the explorer like window you see above in C#. Using the example application, you would transfer the files or folders by selecting them either in explorer and dragging them to the right pane in the transfer window, or selecting them in the transfer window's right pane and dragging them to an explorer window.
What we have here is very fast FTP like functionality, without the hassle most FTP clients normally come with. Instead of offering drag and drop functionality, many force you to deal with an antiquated feeling interface that has a separate window displaying the contents of the file systems of both the local and remote machine.
Using this example as a guide, you will be able to quickly build file and folder transfer functionality into your network application using the TcpComm
library found here.
Even though I used the TcpComm
library for this example project, you are not locked into it. I designed the RemoteFileSystem
class (the class responsible for talking to the remote machine and getting file system information) to be a complete and separate entity, capable of being used with any network communications library. So if you have another network library you're more comfortable with, or would like to write your own, you will not have to tear TcpComm
out of this project and force yours in, you can simply drop the RemoteFileSystem
class into your project.
Background
I wrote and published the TcpComm
library here on CodeProject in 2012. Over the years, people have asked me how to transfer folders. The library provides GetFile()
and SendFile()
functions in both the client and server classes... and I also provided a way to change the folder used by the client and server to receive incoming files. So when I was asked, most of the time I would just tell people that they needed to build folder transfer functionality into their application themselves. I would say that I had provided the tools, that the rest was up to you.
Recently, an application that I was working on required me to do exactly that - build a UI that showed the file system of a remote machine, and provide a way to transfer files between the local and remote machines. I wanted the interface to be fairly intuitive, so the clunky old Cute FTP style interface that had a separate window for each file system was out. I decided to build this functionality in a separate testbed application, and use the TcpComm
library during testing so I could make sure the file transfer code in TcpComm
was as tight as possible and also finally provide that example of how to transfer folders for people who have been asking over the years.
Using the Code
At the heart of this application, is the RemoteFileSystem
class. It has its own client and server classes, and it is responsible for handling requests for information about the remote file system. The RemoteFileSystem.Server
accepts requests in string
form sent from the RemoteFileSystem.Client
. The requests are formatted as XML, using an XML parser I built (XmlObject
).
RFS (RemoteFileSystem
) doesn't send any data over the network itself, it passes each request or response to your network communications library of choice via a delegate. In the example project, the code required to initialize the RFS server is very brief.
The RFS Server constructor looks like this:
rfsServer = new RemoteFileSystem.Server((String data) =>
{
UI(() => LblStatus.Text = "Sending data to client.");
lat.SendArray(TcpComm.Utilities.StrToByteArray(data), 100, currentSessionId, ref errMsg);
}, (String newPath) =>
{
var session = tcpServer.GetSession(currentSessionId);
if (session != null) { session.ReceivedFilesFolder = newPath; }
});
By contrast, the client constructor is quite lengthy because the server's reply data is being parsed, and used to populate a Treeview
and a ListView
control:
private void StartRFS()
{
rfsClient = new RemoteFileSystem.Client((String data) =>
{
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) =>
{
if (serverData.type.Equals("getdrives"))
{
UI(() =>
{
tvPaths.Nodes.Clear();
tvPaths.Nodes.Add("", remoteMachineName, 3);
TreeNode firstNode = tvPaths.Nodes[0];
...
This project is heavily commented. My intent was to have interested parties read through the example project so they can get a handle on how to use the different pieces of this puzzle.
Points of Interest
- When testing this project, if you decide to test the server on a separate network machine, make sure you start the server by right clicking it and running it as Administrator. If you don't, then the server application will not have access to the file system and will quietly close the first time you connect to it.
- When you attempt to connect to the server running on a separate machine, make sure you specify the port in the connection string by separating the IP address or hostname with a colon, i.e.: your_IP_address_or_hostname:22490
- This example project contains a copy of
XmlObject
- an XML parser I wrote. It's built on top of XmlReader
, so no - I wasn't trying to do anything groundbreaking. I just wanted to wrap the functionality that I was most likely to use, and make it usable in the way that I think we're all most comfortable with. For instance, when I look at XML, I see a collection of nested objects. So when I'm accessing the XML with my parser, I don't want to traverse nodes, or worry about illegal characters. I want to simply access my object, and get at its child objects easily like any other OO programmer. - This project also contains a couple of helper classes. One is the
CopyFile
helper class. It does all the heavy lifting involved with transferring the files and displaying progress. - The other is the
DragDrop
helper class. This offers the ability to get the name of the Windows Explorer folder the end user is dragging TO, because Windows doesn't offer that natively. Much of the code in this class was originally found here.
However, I have taken Mr Joy's example and completely rewritten it as a simple helper class, instead of a project spanning example. I have also refined it, so that you never see the dropped file, even if it's dropped onto the desktop.
Lastly, I have tested this application in Windows 7, Windows 10 and Windows Server 2012. In all of these OSs, it works properly. If you discover that it doesn't work properly in Windows 8, or Windows XP, please feel free to let me know below.
History
- 2nd May, 2017: Initial version