FluentFTP
FluentFTP copied to clipboard
UploadFile does not restore the working directory when auto-restoring the connection
FTP OS: unknown
FTP Server: ProFTPD
Computer OS: Windows 10
FluentFTP Version: 34.0.2
When UploadFile auto-restores the connection, the remote working directory is not restored. Thus, part of the file ends up in the desired directory, while the remainder of the file ends up in the root directory.
Code:
Here is the minimal repro example I used to reproduce this issue. I had to execute the code multiple times, because the "stale data" issue only happens every now and then.
using FluentFTP;
using FluentFTP.Helpers;
public class Program
{
public static void Main(string[] args)
{
string host = "---redacted---";
string user = "---redacted---";
string pass = "---redacted---";
string remoteFolder = "/---redacted---/public/software";
string localfile = @"C:\Temp\uploadtest.zip";
string filename = "uploadtest.zip";
FtpTrace.LogToConsole = true;
FtpTrace.LogUserName = false;
FtpTrace.LogPassword = false;
FtpTrace.LogIP = false;
using (var client = new FtpClient(host, user, pass))
{
client.EncryptionMode = FtpEncryptionMode.Explicit;
client.Connect();
client.SetWorkingDirectory(remoteFolder);
if (client.FileExists(filename))
client.DeleteFile(filename);
client.UploadFile(localfile, filename, FtpRemoteExists.Overwrite);
}
}
}
Logs:
Note: I redacted the first subfolder name, since it contains a domain name, as well as the FTP user name (it was visible in the FTP server replies).
# Connect()
Status: Connecting to ***:21
Response: 220 ProFTPD Server (ProFTPD) [188.68.47.190]
Status: Detected FTP server: ProFTPD
Command: AUTH TLS
Response: 234 AUTH TLS successful
Status: FTPS Authentication Successful
Status: Time to activate encryption: 0h 0m 0s. Total Seconds: 0,0766189.
Command: USER ***
Response: 331 Password required for ---redacted---
Command: PASS ***
Response: 230 User ---redacted--- logged in
Command: PBSZ 0
Response: 200 PBSZ 0 successful
Command: PROT P
Response: 200 Protection set to Private
Command: FEAT
Response: 211-Features:
Response: AUTH TLS
Response: CCC
Response: CLNT
Response: EPRT
Response: EPSV
Response: HOST
Response: LANG en-US*
Response: MDTM
Response: MFF modify;UNIX.group;UNIX.mode;
Response: MFMT
Response: MLST modify*;perm*;size*;type*;unique*;UNIX.group*;UNIX.groupname*;UNIX.mode*;UNIX.owner*;UNIX.ownername*;
Response: PBSZ
Response: PROT
Response: RANG STREAM
Response: REST STREAM
Response: SIZE
Response: SSCN
Response: TVFS
Response: UTF8
Response: 211 End
Status: Text encoding: System.Text.UTF8Encoding
Command: OPTS UTF8 ON
Response: 200 UTF8 set to on
Command: SYST
Response: 215 UNIX Type: L8
# SetWorkingDirectory("/---redacted---/public/software")
Command: CWD /---redacted---/public/software
Response: 250 CWD command successful
# FileExists("uploadtest.zip")
# GetWorkingDirectory()
Command: PWD
Response: 257 "/---redacted---/public/software" is the current directory
Command: SIZE /---redacted---/public/software/uploadtest.zip
Response: 213 62521036
# DeleteFile("uploadtest.zip")
Command: DELE uploadtest.zip
Response: 250 DELE command successful
# UploadFile("C:\Temp\uploadtest.zip", "uploadtest.zip", Overwrite, False, None)
# FileExists("uploadtest.zip")
# GetWorkingDirectory()
Command: PWD
Response: 257 "/---redacted---/public/software" is the current directory
Command: SIZE /---redacted---/public/software/uploadtest.zip
Response: 550 /---redacted---/public/software/uploadtest.zip: No such file or directory
# OpenWrite("uploadtest.zip", Binary)
Command: TYPE I
Response: 200 Type set to I
# OpenPassiveDataStream(AutoPassive, "STOR uploadtest.zip", 0)
Command: EPSV
Response: 229 Entering Extended Passive Mode (|||64941|)
Status: Connecting to ***:64941
Command: STOR uploadtest.zip
Response: 150 Opening BINARY mode data connection for uploadtest.zip
Status: FTPS Authentication Successful
Status: Time to activate encryption: 0h 0m 0s. Total Seconds: 0,0247197.
Status: Disposing FtpSocketStream...
# OpenAppend("uploadtest.zip", Binary)
# GetFileSize("uploadtest.zip")
Status: There is stale data on the socket, maybe our connection timed out or you did not call GetReply(). Re-connecting...
Status: Disposing FtpSocketStream...
# Connect()
Status: Connecting to ***:21
Response: 220 ProFTPD Server (ProFTPD) [188.68.47.190]
Status: Detected FTP server: ProFTPD
Command: AUTH TLS
Response: 234 AUTH TLS successful
Status: FTPS Authentication Successful
Status: Time to activate encryption: 0h 0m 0s. Total Seconds: 0,056682.
Command: USER ***
Response: 331 Password required for ---redacted---
Command: PASS ***
Response: 230 User ---redacted--- logged in
Command: PBSZ 0
Response: 200 PBSZ 0 successful
Command: PROT P
Response: 200 Protection set to Private
Command: FEAT
Response: 211-Features:
Response: AUTH TLS
Response: CCC
Response: CLNT
Response: EPRT
Response: EPSV
Response: HOST
Response: LANG en-US*
Response: MDTM
Response: MFF modify;UNIX.group;UNIX.mode;
Response: MFMT
Response: MLST modify*;perm*;size*;type*;unique*;UNIX.group*;UNIX.groupname*;UNIX.mode*;UNIX.owner*;UNIX.ownername*;
Response: PBSZ
Response: PROT
Response: RANG STREAM
Response: REST STREAM
Response: SIZE
Response: SSCN
Response: TVFS
Response: UTF8
Response: 211 End
Status: Text encoding: System.Text.UTF8Encoding
Command: OPTS UTF8 ON
Response: 200 UTF8 set to on
Command: SYST
Response: 215 UNIX Type: L8
Command: SIZE uploadtest.zip
Response: 213 133745833
# OpenPassiveDataStream(AutoPassive, "APPE uploadtest.zip", 0)
Command: EPSV
Response: 229 Entering Extended Passive Mode (|||65146|)
Status: Connecting to ***:65146
Command: APPE uploadtest.zip
Response: 150 Opening BINARY mode data connection for uploadtest.zip
Status: FTPS Authentication Successful
Status: Time to activate encryption: 0h 0m 0s. Total Seconds: 0,0229996.
Status: Disposing FtpSocketStream...
Response: 226 Transfer complete
# Dispose()
Status: Disposing FtpClient object...
Command: QUIT
Response: 221 Goodbye.
Status: Disposing FtpSocketStream...
Status: Disposing FtpSocketStream...
Excellent find. We will check out the failing code and let you know.
On Thu, Aug 26, 2021, 4:32 PM HeinziAT @.***> wrote:
FTP OS: unknown
FTP Server: ProFTPD
Computer OS: Windows 10
FluentFTP Version: 34.0.2
When UploadFile auto-restores the connection, the remote working directory is not restored. Thus, part of the file ends up in the desired directory, while the remainder of the file ends up in the root directory.
Code:
Here is the minimal repro example I used to reproduce this issue. I had to execute the code multiple times, because the "stale data" issue only happens every now and then.
using FluentFTP; using FluentFTP.Helpers;
public class Program { public static void Main(string[] args) { string host = "---redacted---"; string user = "---redacted---"; string pass = "---redacted---";
string remoteFolder = "/---redacted---/public/software"; string localfile = @"C:\Temp\uploadtest.zip"; string filename = "uploadtest.zip"; FtpTrace.LogToConsole = true; FtpTrace.LogUserName = false; FtpTrace.LogPassword = false; FtpTrace.LogIP = false; using (var client = new FtpClient(host, user, pass)) { client.EncryptionMode = FtpEncryptionMode.Explicit; client.Connect(); client.SetWorkingDirectory(remoteFolder); if (client.FileExists(filename)) client.DeleteFile(filename); client.UploadFile(localfile, filename, FtpRemoteExists.Overwrite); } }
}
Logs:
Note: I redacted the first subfolder name, since it contains a domain name, as well as the FTP user name (it was visible in the FTP server replies).
Connect()
Status: Connecting to :21 Response: 220 ProFTPD Server (ProFTPD) [188.68.47.190] Status: Detected FTP server: ProFTPD Command: AUTH TLS Response: 234 AUTH TLS successful Status: FTPS Authentication Successful Status: Time to activate encryption: 0h 0m 0s. Total Seconds: 0,0766189. Command: USER *** Response: 331 Password required for ---redacted--- Command: PASS *** Response: 230 User ---redacted--- logged in Command: PBSZ 0 Response: 200 PBSZ 0 successful Command: PROT P Response: 200 Protection set to Private Command: FEAT Response: 211-Features: Response: AUTH TLS Response: CCC Response: CLNT Response: EPRT Response: EPSV Response: HOST Response: LANG en-US Response: MDTM Response: MFF modify;UNIX.group;UNIX.mode; Response: MFMT Response: MLST modify;perm;size*;type*;unique*;UNIX.group*;UNIX.groupname*;UNIX.mode*;UNIX.owner*;UNIX.ownername*; Response: PBSZ Response: PROT Response: RANG STREAM Response: REST STREAM Response: SIZE Response: SSCN Response: TVFS Response: UTF8 Response: 211 End Status: Text encoding: System.Text.UTF8Encoding Command: OPTS UTF8 ON Response: 200 UTF8 set to on Command: SYST Response: 215 UNIX Type: L8
SetWorkingDirectory("/---redacted---/public/software")
Command: CWD /---redacted---/public/software Response: 250 CWD command successful
FileExists("uploadtest.zip")
GetWorkingDirectory()
Command: PWD Response: 257 "/---redacted---/public/software" is the current directory Command: SIZE /---redacted---/public/software/uploadtest.zip Response: 213 62521036
DeleteFile("uploadtest.zip")
Command: DELE uploadtest.zip Response: 250 DELE command successful
UploadFile("C:\Temp\uploadtest.zip", "uploadtest.zip", Overwrite, False, None)
FileExists("uploadtest.zip")
GetWorkingDirectory()
Command: PWD Response: 257 "/---redacted---/public/software" is the current directory Command: SIZE /---redacted---/public/software/uploadtest.zip Response: 550 /---redacted---/public/software/uploadtest.zip: No such file or directory
OpenWrite("uploadtest.zip", Binary)
Command: TYPE I Response: 200 Type set to I
OpenPassiveDataStream(AutoPassive, "STOR uploadtest.zip", 0)
Command: EPSV Response: 229 Entering Extended Passive Mode (|||64941|) Status: Connecting to ***:64941 Command: STOR uploadtest.zip Response: 150 Opening BINARY mode data connection for uploadtest.zip Status: FTPS Authentication Successful Status: Time to activate encryption: 0h 0m 0s. Total Seconds: 0,0247197. Status: Disposing FtpSocketStream...
OpenAppend("uploadtest.zip", Binary)
GetFileSize("uploadtest.zip")
Status: There is stale data on the socket, maybe our connection timed out or you did not call GetReply(). Re-connecting... Status: Disposing FtpSocketStream...
Connect()
Status: Connecting to :21 Response: 220 ProFTPD Server (ProFTPD) [188.68.47.190] Status: Detected FTP server: ProFTPD Command: AUTH TLS Response: 234 AUTH TLS successful Status: FTPS Authentication Successful Status: Time to activate encryption: 0h 0m 0s. Total Seconds: 0,056682. Command: USER *** Response: 331 Password required for ---redacted--- Command: PASS *** Response: 230 User ---redacted--- logged in Command: PBSZ 0 Response: 200 PBSZ 0 successful Command: PROT P Response: 200 Protection set to Private Command: FEAT Response: 211-Features: Response: AUTH TLS Response: CCC Response: CLNT Response: EPRT Response: EPSV Response: HOST Response: LANG en-US Response: MDTM Response: MFF modify;UNIX.group;UNIX.mode; Response: MFMT Response: MLST modify;perm;size*;type*;unique*;UNIX.group*;UNIX.groupname*;UNIX.mode*;UNIX.owner*;UNIX.ownername*; Response: PBSZ Response: PROT Response: RANG STREAM Response: REST STREAM Response: SIZE Response: SSCN Response: TVFS Response: UTF8 Response: 211 End Status: Text encoding: System.Text.UTF8Encoding Command: OPTS UTF8 ON Response: 200 UTF8 set to on Command: SYST Response: 215 UNIX Type: L8 Command: SIZE uploadtest.zip Response: 213 133745833
OpenPassiveDataStream(AutoPassive, "APPE uploadtest.zip", 0)
Command: EPSV Response: 229 Entering Extended Passive Mode (|||65146|) Status: Connecting to ***:65146 Command: APPE uploadtest.zip Response: 150 Opening BINARY mode data connection for uploadtest.zip Status: FTPS Authentication Successful Status: Time to activate encryption: 0h 0m 0s. Total Seconds: 0,0229996. Status: Disposing FtpSocketStream... Response: 226 Transfer complete
Dispose()
Status: Disposing FtpClient object... Command: QUIT Response: 221 Goodbye. Status: Disposing FtpSocketStream... Status: Disposing FtpSocketStream...
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/robinrodricks/FluentFTP/issues/750, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABT3UKTNAFBGRIRSUP53EITT6YNN3ANCNFSM5C3DB2UQ . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&utm_campaign=notification-email .
Thanks! We currently use the workaround of avoiding SetWorkingDirectory
and using absolute paths instead, so it's not urgent on our side.
Any reason you are calling client.FileExists
on your end? UploadFile
does that internally already...
Re FileExists and DeleteFile: That's just an artefact of creating a minimal example. Our real script uploads two files, which should be in sync. If anything goes wrong, we don't want to risk one of them being old and the other one being new, so we delete both old files before uploading the new ones.
I wasn't able to reproduce the issue with just UploadFile, so I added that part back in. Maybe it's required to trigger the "stale data" issue, maybe it isn't... I can't say since that issue cannot be reproduced reliably.
The newest FluentFTP (V42.0.3) will restore the CWD after a reconnect. This is fixed.
Also: The "stale data" is shown in the log and would indicate the actual error that occurred.