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 files@domain.co.il
Trace: CFtpControlSocket::OnReceive()
Trace: CFtpControlSocket::OnReceive()
Response: 331 User files@domain.co.il 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%40domain.co.il@11.111.111.11: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%40domain.co.il@11.111.111.11: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%40domain.co.il@11.111.111.11: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()