如何通过 .net 控制台应用程序从 ftp 服务器下载名称中包含希伯来字符的文件?

How can I download a file with Hebrew characters in its name from an ftp server via .net console application?

我正在使用用 C# 编写的 .net 控制台应用程序定期从 ftp 服务器下载某些文件,它曾经正常工作,直到有一个带有希伯来字符的文件,名称如下:

1234--אבג.jpeg

所以我尝试使用 chrome 和 FileZilla 下载同一个文件 - 没有遇到任何问题,既没有文件名的普通版本也没有 URL 编码版本。

我的问题是如何使用我的 C# 应用程序下载相同的文件

我试过:

这是我的代码:

 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 remote server returned an error: (550) File unavailable (e.g., file not found, no access).

在 Filezilla 中它是成功的

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()

虽然我没有找到错误的确切原因,但在按照评论中的建议打印 FileZilla 详细日志和 FtpWebRequest 并阅读更多内容后,我了解到很难使用 System.Net.WebRequest 更改某些配置和 HttpClient,所以我使用了 3d 方库 (FluentFTP),有很多可用的配置,但我不需要做任何事情,默认配置解决了问题。