Transfer Aborted. Link To File Server Lost

Sep 18, 2013 at 3:01 PM
First off, thank you for your hard work on this project.

I seem to notice a few threads on here mentioning the same kind of problems, but all these threads have died without any real conclusive answer.

I am using .Net.FtpClient to connect to a FTP server over FTPS. Everything works fine, until I attempt to begin a file download. I begin reading/writing the stream, but the client throws an exception after a few kb is transferred: "Transfer Aborted. Link To File Server Lost". When I open the file, I can see the first few rows of data (it's a spreadsheet) but then it abruptly ends.

I have tried every suggestion that I could find on these forums. These include:
  • Turning EnableThreadSafeDataConnections to false. (tried it set to true too)
  • Upped all Timeouts (ReadTimeout, DataConnectionConnectTimeout, DataConnectionReadTimeout, ConnectTimeout)
  • Tried SocketKeepAlive set to True
  • Tried setting Poll Interval to smaller intervals(2 sec, 1 sec, .5 sec...)
  • Tried both Passive and Active (Active doesn't work at all with this server... just hangs.)
  • Tried Implicit and Explicit Certification (I found only Explicit works for the server I'm connecting to)
  • Tried executing a separate thread that sends NOOP commands over the command channel, at 2 second, then 1 second, and finally .5 second intervals. All three attempts failed.
I tried to turn on FTPTrace following the example but after creating the Log File, it didn't write any data to the file. I didn't debug to solve why yet, because that just added a new problem to solve into the mix. Perhaps my implementation for FTPTrace was wrong.

I've tried downloading the files via FileZille and CuteFTP with no problems and no indicator of anything 'special' going on in the console output.


Here is some of my code:
using (var myFTP = new FtpClient())
            {
                var credentials = new NetworkCredential();
                credentials.UserName = _ftpUsername;
                credentials.Password = _ftpPassword;
                myFTP.Credentials = credentials;
                myFTP.Host = _ftpServer;
                myFTP.EnableThreadSafeDataConnections = false;
                myFTP.EncryptionMode = FtpEncryptionMode.Explicit;
                myFTP.DataConnectionEncryption = true;
                myFTP.ValidateCertificate += new FtpSslValidation(OnValidateCertificate);
                myFTP.SocketKeepAlive = true;
                myFTP.Connect();

                //begin FTP stream
                using (Stream inputStream = myFTP.OpenRead(_reconcileDirectory + "\\" + fileName, FtpDataType.Binary, 15))
                {
                    try
                    {
                        FTPStreamHelper.SaveStreamToFile(path, inputStream);
                    }
                    catch (Exception ex)
                    {
                       //exception handling
                    }
                }
            }

 public static FileInfo SaveStreamToFile(string fileFullPath, Stream stream)
        {
            FileInfo newFile = null;

            if (stream.Length != 0)
            {
                // Create a FileStream object to write a stream to a file
                using (FileStream fileStream = System.IO.File.Create(fileFullPath, (int)stream.Length))
                {
                    // Fill the bytes[] array with the stream data
                    var bytesInStream = new byte[stream.Length];
                    stream.Read(bytesInStream, 0, (int)bytesInStream.Length);

                    // Use FileStream object to write to the specified file
                    fileStream.Write(bytesInStream, 0, bytesInStream.Length);

                    newFile = new FileInfo(fileFullPath);
                }
            }

            return newFile;
        }
examples of FtpTrace implementation (invoked above the myFTP using statement when used)
            FtpTrace.AddListener(new TextWriterTraceListener(_dumppath + "\\log_file.txt"));
            FtpTrace.AddListener(new ConsoleTraceListener());
Log file is created but empty, no output in console. DEBUG is flagged in VS. File begins to transfer... abruptly ends. Operation works in full-scale FTP clients e.g. FileZilla, CuteFTP... I'm at a loss. Any ideas? Thanks for your time!
Sep 20, 2013 at 3:49 PM
Any one out there?
Coordinator
Sep 21, 2013 at 2:43 AM
Sorry for the late reply, been too busy to look into this. The error message is from the server, not from within System.Net.FtpClient. With regards to the log file, I'm not sure what's going on there. You should be able to add trace listeners even in the release builds. The debug requirement was dropped a while back. Which version of System.Net.FtpClient are you running?
Coordinator
Sep 21, 2013 at 2:53 AM
Also, your SaveStreamToFile method isn't exactly correct.The biggest reason is that the file size may not be available so trying to allocate a buffer on the length property of the stream is not a good idea, you need to use a loop and you need to Read() until you get 0 bytes returned. The length property may or may not be non-zero. The other reason is you're allocating an unknown amount of memory, if the file was large this would most likely present a problem. The download examples should illustrate proper usage of the stream object returned from OpenRead().
Sep 21, 2013 at 3:51 AM
Edited Sep 21, 2013 at 3:52 AM
Thanks JP!

I have also read in my research that the message is from the Server, but in some posts I found that this message can be returned as a result of something wrong in the FTP client itself. For instance, if the Control port were to get closed while the transfer was taking place, say by a router, switch, or load balancer because of an Idle port. I've been trying to check that, but so far I haven't found any evidence to support that scenario is taking place.

I can download the files fine through any desktop FTPclient, and I've been in contact with the Network Admin @ the company. He believes the error is in the code because this is the first he's ever heard of this issue (big company with a lot of people connecting to their FTP daily). He verified all of the connection settings that I set in my code, and I've been pouring over it myself. But my implementation seems correct.. so is something in the .Net.FtpClient source not cooperating with their server maybe?

As for the SaveStreamToFile, I'll try changing it as you said. I'm usually pretty sure of the bytes in the file before hand because in many of these scenarios I'm running the bytes into hash checksums remotely and locally to verify the file is correct after download. Considering the nature of my business, we need to know the file size beforehand to validate it upon download via hash, else we aren't confident in the data. Currently I have this implemented already for SFTP w/ Tamir.SharpSSH. However I have not yet applied this check with this library (for FTPS). None the less, I will try implementing the SaveStreamToFile in other ways and see what happens. As for the unknown amount of memory, the files in questions are always only one type of file, and generally always within a range of 1mb +/-. Our solution is for a very static purpose where we always expect the server to be capable file size and hash.


As for the version, I built from changeset 6b8077d9fdeb. I'm away from the office for the weekend, but I'll check it out again next week.

Thanks again for the help!
Coordinator
Sep 21, 2013 at 12:37 PM
Alright, if you could go ahead and update the latest source revision. The first thing that needs to be done is figure out why it's not writing to the trace listeners you're adding. The complete conversation with the server is logged there in addition to exceptions caught internally so there might be some clues as to what's going wrong there. The second thing is I'd like you to try a transfer without SSL. This project uses SslStream, part of the .net framework, internally so I can't offer much guidance by way of debugging SSL related issues (and I have seen some oddities through out the life of this project) so lets eliminate it as well and see where there puts things. The problems I've seen with SSL are usually with a large number of transfers of small files, not a one off transfer, but non the less in an effort to debug the issue take it out. Last thing is to use something like Wireshark to get a packet dump of the FTP session between System.Net.FtpClient and the server, particularly we're looking for RST packets or any kind of pre-mature closure of the socket. I dealt with this issue the other day when closing the control connection, for another user of this project. The server was pre-maturely closing when sending QUIT which causes an exception on the client end.