FluentFTP: UploadFileAsync not working with old FTP-Server (but UploadFile works)

FTP OS: Unix

FTP Server: No information available, unfortunately.

Computer OS: : Windows 10 x64 (Version 1809). .NET 4.6.1 MSIL Application. FluentFTP 24.0.0

I’m trying to upload a simple text file to a rather old FTP server.

  • It works when I use the synchronous method: “UploadFile”.
  • It works when I use the asynchronous method “UploadFileAsync” AND when the remote file already exists.
  • But it fails when I use the asynchronous method “UploadFileSync” AND when the remote file does not exist.

Isolation:

  • The problem occurs the vast majority of the time, although the UploadAsync method does work on rare occasions.
  • The same transfer using Filezilla works all the time.
  • It works when using the asynchronous method “UploadSync” to other FTP-Servers.
  • The Encoding and DataType are unrelated to the problem.

Here is the InnerException:

FluentFTP.FtpException: Error while uploading the file to the server. See InnerException for more info. ---> System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. ---> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host
   at System.Net.Sockets.Socket.BeginReceive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags, AsyncCallback callback, Object state)
   at System.Net.Sockets.NetworkStream.BeginRead(Byte[] buffer, Int32 offset, Int32 size, AsyncCallback callback, Object state)
   --- End of inner exception stack trace ---
   at System.Net.Sockets.NetworkStream.BeginRead(Byte[] buffer, Int32 offset, Int32 size, AsyncCallback callback, Object state)
   at System.IO.Stream.<>c.<BeginEndReadAsync>b__43_0(Stream stream, ReadWriteParameters args, AsyncCallback callback, Object state)
   at System.Threading.Tasks.TaskFactory`1.FromAsyncTrim[TInstance,TArgs](TInstance thisRef, TArgs args, Func`5 beginMethod, Func`3 endMethod)
   at System.IO.Stream.BeginEndReadAsync(Byte[] buffer, Int32 offset, Int32 count)
   at System.IO.Stream.ReadAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken)
   at FluentFTP.FtpSocketStream.<ReadAsync>d__68.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at FluentFTP.FtpDataStream.<ReadAsync>d__16.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at FluentFTP.FtpSocketStream.<ReadLineAsync>d__71.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at FluentFTP.FtpClient.<GetNameListingAsync>d__378.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at FluentFTP.FtpClient.<FileExistsAsync>d__458.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at FluentFTP.FtpClient.<UploadFileInternalAsync>d__312.MoveNext()
   --- End of inner exception stack trace ---
   at FluentFTP.FtpClient.<UploadFileInternalAsync>d__312.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at FluentFTP.FtpClient.<UploadFileFromFileAsync>d__306.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at FluentFTP.FtpClient.<UploadFileAsync>d__304.MoveNext()

Code:

            const FtpDataType dataType = FtpDataType.ASCII;
            using (_client = new FtpClient()
            {
                Host = host,
                Credentials = new NetworkCredential(user, password),
                Encoding = Encoding.GetEncoding("ISO-8859-1"),
                UploadDataType = dataType,
                DownloadDataType = dataType,
            })
            {
                try
                {
#if false
                    Task.Run(() => _client.UploadFile(file2Upload, $"/data/TestFile.txt")).Wait();
#else
                    _client.UploadFileAsync(file2Upload, "/data/TestFile.txt").Wait();
#endif
                }
                catch (AggregateException e)
                {
                    foreach (var ie in e.InnerExceptions)
                    {
                        Console.WriteLine("*************************************************");
                        Console.WriteLine(ie);
                    }
                }
            }

Sorry, I don’t have much info about the FTP-Server! I understand this is an old FTP-Server, but what puzzles me is that the synchronous methods do work and not the async ones.

Logs :

# UploadFileAsync("TestFile.txt", "/data/TestFile.txt", Overwrite, False, None)

# FileExistsAsync("/data/TestFile.txt")

# Connect()
Status:   Connecting to XXXXXXXXXXXXX:21
Response: 220 Homegate FTP Server ready
Command:  USER XXXXXXXX
Response: 331 Password required for testrem
Command:  PASS ***
Response: 230 Login OK
Command:  FEAT
Response: 211 End
Response: 211-Features supported
Response: REST STREAM
Response: EPRT
Response: EPSV
Response: SIZE
Response: MDTM
Response: MFMT
Response: AUTH
Response: PBSZ
Response: PROT
Response: MLST type*;size*;modify*;
Response: MLSD
Response: UTF8
Response: MODE Z
Status:   Text encoding: System.Text.Latin1Encoding
Command:  SYST
Response: 215 UNIX Type: L8
Status:   Auto-detected UNIX listing parser
Command:  SIZE /data/TestFile.txt
Response: 550 Can't find file "TestFile.txt".
Command:  MDTM /data/TestFile.txt
Response: 550 Can't find file

# GetNameListingAsync("/data")
Command:  TYPE I
Response: 200 Type set to I.

# OpenPassiveDataStreamAsync(AutoPassive, "NLST /data", 0)
Command:  EPSV
Response: 229 Entering Passive Mode (|||63270|)
Status:   Connecting to XXXXXXXXXXXXX:63270
Command:  NLST /data
Response: 226 Transfer complete
Status:   Disposing FtpSocketStream...

# CloseDataStream()
Status:   Disposing FtpSocketStream...
### Exception thrown: 'System.AggregateException' in mscorlib.dll

# Dispose()
Status:   Disposing FtpClient object...
Command:  QUIT
Response: 221 Good-Bye
Status:   Disposing FtpSocketStream...
Status:   Disposing FtpSocketStream...

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 21 (11 by maintainers)

Most upvoted comments

Thanks. I’ll try to fix that one then we can close this issue.

@robinrodricks ,

I have validated the fixes of Bug 1 and 2. UploadFileAsync now works fine in our test config.

As we thought, GetNameListing and GetNameListingAsync are still throwing when the remote folder is empty.

Kind regards, Reureu

@robinrodricks,

Thanks for fixing the first 2 bugs!

About the failing GetNameListingAsync when getting the file list in a specific folder.

  • It works all the time if the folder contains any file.
  • It very often fails if the folder contains no file. It does work on rare occasions though.

I tried to add a few Thread.Sleep() in a few spots to see if it was a timing issue.

I managed to see an improvement by adding a Sleep() in one spot. But that would definitely not be the right way to resolve it, and I didn’t really want to debug the NetworkSocket stuffs.

So I tried the same test with WebRequestMethods.Ftp.ListDirectory (https://docs.microsoft.com/en-us/dotnet/api/system.net.webrequestmethods.ftp.listdirectory), and saw it works all the time.

I can try to get you a test account on this old FTP server, but it will probably take a few days, as it is a bank holiday week-end in our country. That would also allow you to troubleshoot Bug 4.

Kind regards, Reureu