FluentFTP: TimeoutException: Downloaded 0 bytes
FTP Server OS: Unix
FTP Server Type: Pure-FTPd
Client Computer OS: Windows
FluentFTP Version: 47.1.0
Framework: .NET 7
We have encountered an issue with FluentFTP. Whenever we attempt to download a file from the FTP server, we consistently encounter a TimeoutException. It’s noteworthy that we have been able to successfully download files using both WinSCP and FileZilla. Strangely, based on the logs, FluentFTP appears to be operating similarly to FileZilla.
It’s worth mentioning that the FTP server is hosted on third-party hardware, limiting our access to its configuration. This hardware comes in two versions, and this issue only occurs with one of the versions.
Here is a small Console App that we have used to reproduce the error:
using FluentFTP;
const string username = "myUsername";
const string password = "myPassword";
const string filename = "MyFile.CSV";
Console.WriteLine("FTP IP:");
var ip = Console.ReadLine();
var ftpClient = new FtpClient(ip, username, password);
ftpClient.Config.LogToConsole = true;
ftpClient.Config.EncryptionMode = FtpEncryptionMode.Explicit;
ftpClient.Config.ValidateAnyCertificate = true;
ftpClient.Config.ReadTimeout = 120_000;
//Trying to use PASV instead of EPSV as FileZila does. Error still exists with or without this line of code.
ftpClient.Config.DataConnectionType = FtpDataConnectionType.PASV;
ftpClient.Connect();
if (!ftpClient.IsConnected)
{
throw new InvalidOperationException("FTP client is not connected.");
}
ftpClient.DownloadFile(filename, filename);
ftpClient.Disconnect();
Logs :
FluentFTP throws TimeoutException, on stuck at Status: Waiting for response to: *DOWNLOAD*:
FTP IP:
10.10.1.161
# Connect(False)
Status: FluentFTP 47.1.0.0(.NET 6.0)
Status: Connecting to IP #1= ***:21
Status: Waiting for a response
Response: 220---------- Welcome to Pure-FTPd [privsep] [TLS] ----------
Response: 220-You are user number 1 of 50 allowed.
Response: 220-Local time is now 11:09. Server port: 21.
Response: 220-This is a private system - No anonymous login
Response: 220-IPv6 connections are also welcome on this server.
Response: 220 You will be disconnected after 15 minutes of inactivity. [738763,381d]
Status: Detected FTP server: PureFTPd
Command: AUTH TLS
Status: Waiting for response to: AUTH TLS
Response: 234 AUTH TLS OK. [1ms]
Warning: SSL Buffering disabled because of .NET 5.0 and later
Status: FTPS authentication successful, lib = .NET SslStream, cipher suite = Tls12 (Aes256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 44550, 256) [97ms]
Command: USER ***
Status: Waiting for response to: USER ***
Response: 331 User *** OK. Password required [51ms]
Command: PASS ***
Status: Waiting for response to: PASS ***
Response: 230 OK. Current directory is / [2,299s]
Command: PBSZ 0
Status: Waiting for response to: PBSZ 0
Response: 200 PBSZ=0 [<1ms]
Command: PROT P
Status: Waiting for response to: PROT P
Response: 200 Data protection level set to "private" [<1ms]
Command: FEAT
Status: Waiting for response to: FEAT
Response: 211-Extensions supported:
Response: EPRT
Response: IDLE
Response: MDTM
Response: SIZE
Response: MFMT
Response: REST STREAM
Response: MLST type*;size*;sizd*;modify*;UNIX.mode*;UNIX.uid*;UNIX.gid*;unique*;
Response: MLSD
Response: AUTH TLS
Response: PBSZ
Response: PROT
Response: UTF8
Response: TVFS
Response: ESTA
Response: PASV
Response: EPSV
Response: SPSV
Response: ESTP
Response: 211 End. [1ms]
Status: Text encoding: System.Text.UTF8Encoding+UTF8EncodingSealed
Command: OPTS UTF8 ON
Status: Waiting for response to: OPTS UTF8 ON
Response: 200 OK, UTF-8 enabled [<1ms]
Command: SYST
Status: Waiting for response to: SYST
Response: 215 UNIX Type: L8 [<1ms]
Status: Listing parser set to: Machine
Command: PWD
Status: Waiting for response to: PWD
Response: 257 "/" is your current location [<1ms]
# DownloadFile("MyFile.CSV", "MyFile.CSV", Overwrite, None)
# OpenRead("MyFile.CSV", Binary, 0, 0)
# GetFileSize("MyFile.CSV")
Command: SIZE MyFile.CSV
Status: Waiting for response to: SIZE MyFile.CSV
Response: 213 18958 [1ms]
Command: TYPE I
Status: Waiting for response to: TYPE I
Response: 200 TYPE is now 8-bit binary [<1ms]
# OpenDataStream("RETR MyFile.CSV", 0)
# OpenPassiveDataStream(PASV, "RETR MyFile.CSV", 0)
Command: PASV
Status: Waiting for response to: PASV
Response: 227 Entering Passive Mode (10,10,1,161,94,246) [<1ms]
Status: PASV advertised a non-routable IPAD. Using original connect dnsname/IPAD
Status: Connecting to IP #1= ***:24310
Command: RETR MyFile.CSV
Status: Waiting for response to: RETR MyFile.CSV
Response: 150-Accepted data connection
Response: 150 18.5 kbytes to download [1,102s]
Warning: SSL Buffering disabled because of .NET 5.0 and later
Status: FTPS authentication successful, lib = .NET SslStream, cipher suite = Tls12 (Aes256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 44550, 256) [34ms]
Status: Downloaded 0 bytes
Status: Closing/Disposing FtpSocketStream(data connection)
Status: Waiting for response to: *DOWNLOAD*
Status: Closing/Disposing FtpSocketStream(data connection)
Unhandled exception. FluentFTP.Exceptions.FtpException: Error while downloading the file from the server. See InnerException for more info.
---> System.TimeoutException: The operation has timed out.
at FluentFTP.Client.BaseClient.BaseFtpClient.GetReplyInternal(String command, Boolean exhaustNoop, Int32 timeOut)
at FluentFTP.Client.BaseClient.BaseFtpClient.GetReplyInternal(String command, Boolean exhaustNoop)
at FluentFTP.FtpClient.DownloadFileInternal(String localPath, String remotePath, Stream outStream, Int64 restartPosition, Action`1 progress, FtpProgress metaProgress, Int64 knownFileSize, Boolean isAppend, Int64 stopPosition)
--- End of inner exception stack trace ---
at FluentFTP.FtpClient.DownloadFileInternal(String localPath, String remotePath, Stream outStream, Int64 restartPosition, Action`1 progress, FtpProgress metaProgress, Int64 knownFileSize, Boolean isAppend, Int64 stopPosition)
at FluentFTP.FtpClient.DownloadFileToFile(String localPath, String remotePath, FtpLocalExists existsMode, FtpVerify verifyOptions, Action`1 progress, FtpProgress metaProgress)
at FluentFTP.FtpClient.DownloadFile(String localPath, String remotePath, FtpLocalExists existsMode, FtpVerify verifyOptions, Action`1 progress)
at Program.<Main>$(String[] args) in FluentFtpConsoleApp\Program.cs:line 23
Log for FileZilla downloading the file successfully:
Status: Connecting to 10.10.1.161:21...
Status: Connection established, waiting for welcome message...
Response: 220---------- Welcome to Pure-FTPd [privsep] [TLS] ----------
Response: 220-You are user number 1 of 50 allowed.
Response: 220-Local time is now 10:20. Server port: 21.
Response: 220-This is a private system - No anonymous login
Response: 220-IPv6 connections are also welcome on this server.
Response: 220 You will be disconnected after 15 minutes of inactivity.
Command: AUTH TLS
Response: 234 AUTH TLS OK.
Status: Initializing TLS...
Status: TLS connection established.
Command: USER ***
Response: 331 User *** OK. Password required
Command: PASS ********
Response: 230 OK. Current directory is /
Command: OPTS UTF8 ON
Response: 200 OK, UTF-8 enabled
Command: PBSZ 0
Response: 200 PBSZ=0
Command: PROT P
Response: 200 Data protection level set to "private"
Status: Logged in
Status: Retrieving directory listing...
Command: PWD
Response: 257 "/" is your current location
Status: Directory listing of "/" successful
Status: Starting download of /MyFile.CSV
Command: TYPE I
Response: 200 TYPE is now 8-bit binary
Command: PASV
Response: 227 Entering Passive Mode (10,10,1,161,229,95)
Command: RETR MyFile.CSV
Response: 150-Accepted data connection
Response: 150 18.5 kbytes to download
Response: 226-File successfully transferred
Response: 226 0.002 seconds (measured here), 8.39 Mbytes per second
Status: File transfer successful, transferred 18.958 bytes in 1 second
About this issue
- Original URL
- State: closed
- Created 10 months ago
- Comments: 16
In that case perhaps you can make it work somehow.
The only thing I can suggest is to query the Pure-FTPd versions from the good and bad systems, and a diff of the config files.
All other things being the same, this is where you will find the difference.