0
votes

I am using a .net console application written in C# to download certain files from an ftp server routinely, it used to work properly until there was a file with Hebrew characters, named something like that:

1234--אבג.jpeg

so I've tried to download the same file using both chrome and FileZilla - and encountered no problems, with neither plain nor URL encoded version of the filename.

My problem is how to download the same file with my C# application

I have tried:

  • to escape the name as URL-encoded, worked for chrome but not my APP
  • to convert the string to utf-8
  • both System.Net.WebRequest and HttpClient
  • finding and taking the name from response of directory listing and pasting into the request, hoping it will have the proper format.

here is my code :

 public static string attachmentToFile(string name, string filename)
    {
        try
        {
      
            string ftpConnection = ConfigurationManager.AppSettings["FtpServer"].ToString();
            string ftpUser = ConfigurationManager.AppSettings["FtpUser"].ToString();
            string ftpPassword = ConfigurationManager.AppSettings["FtpPassword"].ToString();
            string attachmentPath = ConfigurationManager.AppSettings["attachmentFolder"].ToString();

            Directory.CreateDirectory(attachmentPath);

            attachmentPath += '\\' + name + Path.GetExtension(filename);


            FtpWebRequest attachmentRequest = (FtpWebRequest)WebRequest.Create(
                new Uri(ftpConnection + "/files_directory/" + filename)
                );


            attachmentRequest.Credentials = new NetworkCredential(ftpUser, ftpPassword);
            attachmentRequest.Method = WebRequestMethods.Ftp.DownloadFile;

            FtpWebResponse response = (FtpWebResponse)attachmentRequest.GetResponse();
            var stream = response.GetResponseStream();
            FileStream saveStream = new FileStream(attachmentPath, FileMode.OpenOrCreate);
            //stream.Seek(0, SeekOrigin.Begin);
            stream.CopyTo(saveStream);
            saveStream.Close();
            return attachmentPath;
        }
        catch (Exception ex)
        {
            Logger.LogError(MethodBase.GetCurrentMethod(), ex, "failed downloading file from server: " + filename);
            return null;
        }
    }

the error is

The remote server returned an error: (550) File unavailable (e.g., file not found, no access).

while in Filezilla it's successful

Trace: CControlSocket::SendNextCommand()
Trace: CFtpLogonOpData::Send() in state 0
Status: Connecting to 11.111.111.11:1111...
Status: Connection established, waiting for welcome message...
Trace: CFtpControlSocket::OnReceive()
Response: 220---------- Welcome to Pure-FTPd [privsep] [TLS] ----------
Response: 220-You are user number 3 of 50 allowed.
Response: 220-Local time is now 09:16. Server port: 1111.
Response: 220-This is a private system - No anonymous login
Response: 220 You will be disconnected after 15 minutes of inactivity.
Trace: CFtpLogonOpData::ParseResponse() in state 1
Trace: CControlSocket::SendNextCommand()
Trace: CFtpLogonOpData::Send() in state 2
Command: AUTH TLS
Trace: CFtpControlSocket::OnReceive()
Response: 234 AUTH TLS OK.
Trace: CFtpLogonOpData::ParseResponse() in state 2
Status: Initializing TLS...
Trace: tls_layer_impl::client_handshake()
Trace: tls_layer_impl::continue_handshake()
Trace: tls_layer_impl::continue_handshake()
Trace: tls_layer_impl::continue_handshake()
Trace: tls_layer_impl::continue_handshake()
Trace: tls_layer_impl::continue_handshake()
Trace: TLS Handshake successful
Trace: Protocol: TLS1.2, Key exchange: ECDHE-RSA, Cipher: AES-256-GCM, MAC: AEAD
Trace: tls_layer_impl::verify_certificate()
Status: Verifying certificate...
Trace: CFtpControlSocket::SetAsyncRequestReply
Status: TLS connection established.
Trace: CControlSocket::SendNextCommand()
Trace: CFtpLogonOpData::Send() in state 6
Command: USER [email protected]
Trace: CFtpControlSocket::OnReceive()
Trace: CFtpControlSocket::OnReceive()
Response: 331 User [email protected] OK. Password required
Trace: CFtpLogonOpData::ParseResponse() in state 6
Trace: CControlSocket::SendNextCommand()
Trace: CFtpLogonOpData::Send() in state 6
Command: PASS ****************
Trace: CFtpControlSocket::OnReceive()
Response: 230 OK. Current restricted directory is /
Trace: CFtpLogonOpData::ParseResponse() in state 6
Trace: CControlSocket::SendNextCommand()
Trace: CFtpLogonOpData::Send() in state 10
Command: OPTS UTF8 ON
Trace: CFtpControlSocket::OnReceive()
Response: 504 Unknown command
Trace: CFtpLogonOpData::ParseResponse() in state 10
Trace: CControlSocket::SendNextCommand()
Trace: CFtpLogonOpData::Send() in state 11
Command: PBSZ 0
Trace: CFtpControlSocket::OnReceive()
Response: 200 PBSZ=0
Trace: CFtpLogonOpData::ParseResponse() in state 11
Trace: CControlSocket::SendNextCommand()
Trace: CFtpLogonOpData::Send() in state 12
Command: PROT P
Trace: CFtpControlSocket::OnReceive()
Response: 200 Data protection level set to "private"
Trace: CFtpLogonOpData::ParseResponse() in state 12
Status: Logged in
Trace: Measured latency of 16 ms
Trace: CFtpControlSocket::ResetOperation(0)
Trace: CControlSocket::ResetOperation(0)
Trace: CFtpLogonOpData::Reset(0) in state 15
Trace: CFtpControlSocket::FileTransfer()
Trace: CControlSocket::SendNextCommand()
Trace: CFtpFileTransferOpData::Send() in state 0
Status: Starting download of /files_directory/1234--אבג.jpeg
Trace: CFtpChangeDirOpData::Send() in state 0
Trace: CFtpChangeDirOpData::Send() in state 2
Command: CWD /files_directory
Trace: CFtpControlSocket::OnReceive()
Response: 250 OK. Current directory is /files_directory
Trace: CFtpChangeDirOpData::ParseResponse() in state 2
Trace: CFtpControlSocket::ResetOperation(0)
Trace: CControlSocket::ResetOperation(0)
Trace: CFtpChangeDirOpData::Reset(0) in state 2
Trace: CFtpFileTransferOpData::SubcommandResult(0) in state 1
Trace: CFtpControlSocket::SetAsyncRequestReply
Trace: CControlSocket::SendNextCommand()
Trace: CFtpFileTransferOpData::Send() in state 5
Trace: CFtpRawTransferOpData::Send() in state 1
Command: TYPE I
Trace: CFtpControlSocket::OnReceive()
Response: 200 TYPE is now 8-bit binary
Trace: CFtpRawTransferOpData::ParseResponse() in state 1
Trace: CControlSocket::SendNextCommand()
Trace: CFtpRawTransferOpData::Send() in state 2
Command: PASV
Trace: CFtpControlSocket::OnReceive()
Response: 227 Entering Passive Mode (11,111,111,11,111,11)
Trace: CFtpRawTransferOpData::ParseResponse() in state 2
Trace: CControlSocket::SendNextCommand()
Trace: CFtpRawTransferOpData::Send() in state 4
Trace: Binding data connection source IP to control connection source IP 10.0.0.13
Trace: tls_layer_impl::client_handshake()
Trace: Trying to resume existing TLS session.
Command: RETR 1234--אבג.jpeg
Trace: tls_layer_impl::continue_handshake()
Trace: CFtpControlSocket::OnReceive()
Response: 150-Accepted data connection
Response: 150 206.6 kbytes to download
Trace: CFtpRawTransferOpData::ParseResponse() in state 4
Trace: CControlSocket::SendNextCommand()
Trace: CFtpRawTransferOpData::Send() in state 5
Trace: tls_layer_impl::continue_handshake()
Trace: TLS Handshake successful
Trace: TLS Session resumed
Trace: Protocol: TLS1.2, Key exchange: ECDHE-RSA, Cipher: AES-256-GCM, MAC: AEAD
Trace: tls_layer_impl::verify_certificate()
Trace: CTransferSocket::OnConnect
Trace: CFtpControlSocket::OnReceive()
Response: 226-File successfully transferred
Trace: CFtpControlSocket::OnReceive()
Response: 226 0.120 seconds (measured here), 1.68 Mbytes per second
Trace: CFtpRawTransferOpData::ParseResponse() in state 5
Trace: CControlSocket::SendNextCommand()
Trace: CFtpRawTransferOpData::Send() in state 8
Trace: CTransferSocket::TransferEnd(1)
Trace: tls_layer_impl::shutdown()
Trace: tls_layer_impl::continue_shutdown()
Trace: CFtpControlSocket::TransferEnd()
Trace: CFtpControlSocket::ResetOperation(0)
Trace: CControlSocket::ResetOperation(0)
Trace: CFtpRawTransferOpData::Reset(0) in state 8
Trace: CFtpFileTransferOpData::SubcommandResult(0) in state 7
Trace: CFtpControlSocket::ResetOperation(0)
Trace: CControlSocket::ResetOperation(0)
Trace: CFtpFileTransferOpData::Reset(0) in state 7
Status: File transfer successful, transferred 211,556 bytes in 1 second
Status: Disconnected from server

network.log

System.Net Information: 0 : [14564] FtpWebRequest#54024015::.ctor(ftp://files%[email protected]:1111/files_directory/22222222-IMG-222222-222222.jpg)
System.Net Information: 0 : [14564] FtpWebRequest#54024015::GetResponse(Method=RETR.)
System.Net Information: 0 : [14564] Current OS installation type is 'Client'.
System.Net Information: 0 : [14564] RAS supported: True
System.Net Information: 0 : [14564] FtpControlStream#13869071 - Created connection from 10.0.0.13:11111 to 11.111.111.11:1111.
System.Net Information: 0 : [14564] Associating FtpWebRequest#54024015 with FtpControlStream#13869071
System.Net Information: 0 : [14564] FtpControlStream#13869071 - Received response [220---------- Welcome to Pure-FTPd [privsep] [TLS] ----------
220-You are user number 3 of 50 allowed.
220-Local time is now 09:44. Server port: 1111.
220-This is a private system - No anonymous login
220 You will be disconnected after 15 minutes of inactivity.]

....

150 119.1 kbytes to download]
System.Net Information: 0 : [14564] FtpControlStream#13869071 - Received response [226-File successfully transferred
226 0.052 seconds (measured here), 2.24 Mbytes per second]

....

150 4312.7 kbytes to download]
System.Net Information: 0 : [14564] FtpControlStream#13869071 - Received response [226-File successfully transferred
226 1.874 seconds (measured here), 2.25 Mbytes per second]

....

150 1974.2 kbytes to download]
System.Net Information: 0 : [14564] FtpControlStream#13869071 - Received response [226-File successfully transferred
226 0.884 seconds (measured here), 2.18 Mbytes per second]
System.Net Information: 0 : [14564] FtpWebRequest#49652976::(Releasing FTP connection#13869071.)
System.Net Information: 0 : [14564] FtpWebRequest#44223604::.ctor(ftp://files%[email protected]:1111/files_directory/11111111-1111111111.jpg)
System.Net Information: 0 : [14564] FtpWebRequest#44223604::GetResponse(Method=RETR.)
System.Net Information: 0 : [14564] Associating FtpWebRequest#44223604 with FtpControlStream#13869071
System.Net Information: 0 : [14564] FtpControlStream#13869071 - Sending command [PASV]
System.Net Information: 0 : [14564] FtpControlStream#13869071 - Received response [227 Entering Passive Mode (11,111,111,11,111,111)]
System.Net Information: 0 : [14564] FtpControlStream#13869071 - Sending command [RETR files_directory/11111111-1111111111.jpg]
System.Net Information: 0 : [14564] FtpControlStream#13869071 - Received response [150-Accepted data connection
150 1953.3 kbytes to download]
System.Net Information: 0 : [14564] FtpControlStream#13869071 - Received response [226-File successfully transferred
226 0.929 seconds (measured here), 2.05 Mbytes per second]
System.Net Information: 0 : [14564] FtpWebRequest#44223604::(Releasing FTP connection#13869071.)
System.Net Information: 0 : [14564] FtpWebRequest#62468121::.ctor(ftp://files%[email protected]:1111/files_directory/1234--אבג.jpeg)
System.Net Information: 0 : [14564] FtpWebRequest#62468121::GetResponse(Method=RETR.)
System.Net Information: 0 : [14564] Associating FtpWebRequest#62468121 with FtpControlStream#13869071
System.Net Information: 0 : [14564] FtpControlStream#13869071 - Sending command [PASV]
System.Net Information: 0 : [14564] FtpControlStream#13869071 - Received response [227 Entering Passive Mode (11,111,111,11,111,111)]
System.Net Information: 0 : [14564] FtpControlStream#13869071 - Sending command [RETR files_directory/1234--אבג.jpeg]
System.Net Information: 0 : [14564] FtpControlStream#13869071 - Received response [550 Can't open files_directory/1234--אבג.jpeg: No such file or directory]
System.Net Information: 0 : [14564] FtpWebRequest#62468121::(Releasing FTP connection#13869071.)
System.Net Error: 0 : [14564] Exception in FtpWebRequest#62468121::GetResponse - The remote server returned an error: (550) File unavailable (e.g., file not found, no access)..
at System.Net.FtpWebRequest.SyncRequestCallback(Object obj)
at System.Net.FtpWebRequest.RequestCallback(Object obj)
at System.Net.CommandStream.Dispose(Boolean disposing)
at System.IO.Stream.Close()
at System.IO.Stream.Dispose()
at System.Net.ConnectionPool.Destroy(PooledStream pooledStream)
at System.Net.ConnectionPool.PutConnection(PooledStream pooledStream, Object owningObject, Int32 creationTimeout, Boolean canReuse)
at System.Net.FtpWebRequest.FinishRequestStage(RequestStage stage)
at System.Net.FtpWebRequest.GetResponse()

1
FTP has a "usebinary" property. Normal FTP mode is text which will filter characters. If you do not want any filtering than use the binary mode.jdweng
And what's the problem you have? Any error? Problems with user input? File not found? be more specificGusman
As @Gusman said, be more specific about the issue you're seeing. You probably need to HttpUtility.UrlEncode the filename.jeroenh
Show us FileZilla verbose log file as well as FtpWebRequest log file.Martin Prikryl
@jdweng The question is about file names, not file contents. Binary/Text mode is irrelevant here.Martin Prikryl

1 Answers

0
votes

although I didn't find the exact reason for the error, after printing FileZilla verbose log and FtpWebRequest as suggested in the comments and reading some more I have read that it's hard to change certain configurations using System.Net.WebRequest and HttpClient, so I used a 3d party library (FluentFTP) there were many configurations available but I didn't need to do anything in my case and the problem was solved by the default configurations.