【问题标题】:Read FTP file with international characters读取带有国际字符的 FTP 文件
【发布时间】:2015-12-05 09:39:24
【问题描述】:

我正在使用以下代码下载 FTP 位置文件。它适用于所有文件,但文件名包含国际字符的文件除外。

我已经学习了 URI 格式,所以这是不允许的,但是如果提到的位置有现有文件,如何下载。

为了测试,我在 IIS 下设置了本地 FTP 服务器,如下所示。

http://www.online-tech-tips.com/computer-tips/setup-ftp-server-in-windows-iis/

string mat_address = "ftp://localhost/";
StringBuilder result = new StringBuilder();
FtpWebRequest ftp = (FtpWebRequest)WebRequest.Create(mat_address);

ftp.Credentials = new NetworkCredential("userid", "Password");
ftp.Method = WebRequestMethods.Ftp.ListDirectory;

string[] downloadfile = null;
using (FtpWebResponse response = (FtpWebResponse)ftp.GetResponse())
using (StreamReader reader = new StreamReader(response.GetResponseStream(), System.Text.Encoding.Default, true))
{
    downloadfile = reader.ReadToEnd().Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
}

foreach (string d in downloadfile)
{
    if (d.Contains("d"))
    {
        string temp = mat_address + HttpUtility.UrlPathEncode(d);
        FtpWebRequest ftp2 = (FtpWebRequest)WebRequest.Create(temp);

        ftp2.Credentials = new NetworkCredential("userid", "Password");

        ftp2.Method = WebRequestMethods.Ftp.GetDateTimestamp;

        ftp2.UseBinary = true;

        ftp2.Proxy = null;
        ftp2.KeepAlive = false;
        ftp2.UsePassive = false;

        FtpWebResponse response2 = ftp2.GetResponse() as FtpWebResponse;
        DateTime temp1 = response2.LastModified.Date;
        if (temp1 > DateTime.Now.AddDays(-10))
        {
           // Some extra work
        }
    }
}

我遇到错误

远程服务器返回错误:(550) 文件不可用(例如,找不到文件,无法访问)。

下面是我的 FTP 根文件夹,有问题的文件名为 diá.png

我使用 C# 进行编码,使用 Visual Studio 2013 进行开发。出了什么问题,有人可以帮忙。

问题更新: 将编码更改为 UTF8。 使用本地主机一切正常。但是当使用来自德国和瑞典等国际域的 FTP 服务器时。名称如下所示。

我收到以下行的错误。

FtpWebResponse response2 = ftp2.GetResponse() as FtpWebResponse;

文件名的十六进制值: Martin 建议包含。谢谢 31,30,31,33,36,2D,49,43,4F,4D,20,50,4A,C4,54,54,45,52,59,44,20,70,69,63,74,20,37‌​,38,78,31,31,38,20,61,6E,6E,69,2D,76,65,72,73,61,72,69,75,73,20,5B,77,31,33,32,31‌​,20,78,20,68,39,32,31,5D,20,6D,6D,20,44,49,46,46,55,53,45,2E,50,4E,47,

【问题讨论】:

    标签: c# .net ftp ftpwebrequest ftpwebresponse


    【解决方案1】:

    大多数 FTP 服务器应使用 UTF-8 编码。您的本地 (IIS) 服务器也是如此。

    所以在解析目录列表时需要使用Encoding.UTF8


    尽管您的真实/生产服务器似乎以某种方式损坏。看起来它对目录列表使用了 Windows-1252 编码。然而,它声称(并且似乎需要)对命令进行 UTF-8 编码。这显然(并且理所当然地)使 FileZilla 感到困惑。但我不明白为什么它不适用于FtpWebRequest,因为它应该使用UTF-8(因为服务器积极响应OPTS utf8 on 命令),并且您尝试显式使用Windows-1252 编码,解析列表时。


    无论如何,正如您(在聊天中)发现 WinSCP 有效,您可以尝试使用WinSCP .NET assembly。它还将使您的代码更简单:

    SessionOptions sessionOptions = new SessionOptions();
    sessionOptions.Protocol = Protocol.Ftp;
    sessionOptions.HostName = "hostname";
    sessionOptions.UserName = "username";
    sessionOptions.Password = "password";
    
    using (Session session = new Session())
    {
        session.Open(sessionOptions);
    
        foreach (RemoteFileInfo fileInfo in session.ListDirectory("/textures").Files)
        {
            if (fileInfo.Name.Contains("d"))
            {
                if (fileInfo.LastWriteTime > DateTime.Now.AddDays(-10))
                {
                    string sourcePath =
                        RemotePath.EscapeFileMask("/textures/" + fileInfo.Name);
                    session.GetFiles(sourcePath, @"c:\local\path\").Check();
                }
            }
        }
    }
    

    或者,更简单,使用file mask with time constraint

    SessionOptions sessionOptions = new SessionOptions();
    sessionOptions.Protocol = Protocol.Ftp;
    sessionOptions.HostName = "hostname";
    sessionOptions.UserName = "username";
    sessionOptions.Password = "password";
    
    using (Session session = new Session())
    {
        session.Open(sessionOptions);
    
        session.GetFiles("/textures/*d*>=10D", @"c:\local\path\").Check();
    }
    

    另见 WinSCP 示例 How do I transfer new/modified files only?

    【讨论】:

    • 我已经更新了我的问题。正如您所说,编码应该是 UTF8,这导致了我的问题,我将从 FTP 服务器读取的文件名出错了。我已将此添加为对原始问题的更新。
    • 所以可能真正的服务器使用Ansi编码。试试Encoding.GetEncoding(1252)。很难猜。向我们展示响应流的十六进制转储。
    • 好的,我会检查的。 @Martin 我将如何获得 HEX 转储。是例外吗?
    • 我可以读取和下载其他文件,但唯一的文件是文件名中包含国际字符的文件。
    • 我已经在第一个 ..bcz 的代码中包含了 session.EscapeFileMask 对我有用
    【解决方案2】:

    我会说,您必须转换接收到的文件名的编码以匹配本地文件系统的需要。你能发布你审查的文件名吗?我认为你得到一个包含一些非法字符的 excaped 字符串......

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-11
      • 2018-07-08
      • 1970-01-01
      • 2016-09-24
      • 2012-04-19
      相关资源
      最近更新 更多