Ftp使用utf-8字符创建文件名,例如希腊语,德语等

时间:2013-11-01 13:19:57

标签: c# encoding utf-8 ftp

我正在尝试使用以下代码为ftp服务器创建一个文件(我也尝试使用UseBinary选项为true和false)

string username = "name";
string password = "password";
string remotefolder = "ftp://ftp.myhost.gr/public_html/test/";
string remoteFileName = "δοκιμαστικό αρχείοüß-äCopy.txt";
string localFile = @"C:\test\δοκιμαστικό αρχείο - Copy.txt";
String ftpname = "ftp://ftp.myhost.gr/public_html/test" + @"/" + Uri.EscapeUriString(Program.remoteFileName);


FtpWebRequest request = (FtpWebRequest)WebRequest.Create(ftpname);
request.Proxy = null;
request.Credentials = new NetworkCredential(username, password);


request.UsePassive = true;
request.KeepAlive = true;
request.Method = WebRequestMethods.Ftp.UploadFile;
request.UseBinary = true;
//request.UseBinary = false;

 byte[] content = System.IO.File.ReadAllBytes(localFile);
 byte[] fileContents = new Byte[content.Length];

 Array.Copy(content, 0, fileContents, 0, content.Length);

 using (Stream uploadStream = request.GetRequestStream())
 {
     int contentLength = fileContents.Length;
     uploadStream.Write(fileContents, 0, contentLength);
 }

 FtpWebResponse response = (FtpWebResponse)request.GetResponse();
 Console.WriteLine(response.ExitMessage);

问题是我的ftp服务器上的文件没有得到名称 我要求哪个包含英语,希腊语和德语字符 - > “δοκιμαστικόαρχείοüß-äCopy.txt

1)我该怎么办?

我更改区域设置后会有一些改进 - >非Unicode程序到希腊语的当前语言,但我仍然想念德语字符。

2)为什么c#程序依赖于此设置?我是否应遵循特殊的方法以避免依赖此设置?

再次出现编码噩梦:(

2 个答案:

答案 0 :(得分:8)

仅仅将字符串编码为UTF8并将其作为文件名发送到FTP服务器是不够的。在过去,所有FTP服务器都只理解ASCII,现在为了保持向后兼容性 - 即使它们是Unicode识别的 - 当它们启动时它们也将所有文件也视为ASCII。

要使一切顺利,您(您的程序)必须首先检查您的服务器能够做什么。客户端连接后服务器发送其功能 - 在您的情况下,您必须检查 FEAT UTF8 。如果你的服务器发送 - 它意味着它理解UTF8。尽管如此 - 即使它理解它 - 您必须明确告诉它,从现在开始,您将发送您的文件名UTF8编码,现在它是您的程序缺少的东西(因为您的服务器支持utf8,如您所述)。

您的客户必须向FTP服务器发送以下 OPTS UTF8 ON 。发送后你可以使用UTF8或者说你的服务器UTF8-ish(可以这么说)。

请阅读此处了解详情Internationalization of the File Transfer Protocol

答案 1 :(得分:4)

在您的代码更改中:

string localFile = @"C:\test\δοκιμαστικό αρχείο - Copy.txt";
String ftpname = "ftp://ftp.myhost.gr/public_html/test" + @"/" + Uri.EscapeUriString(Program.remoteFileName);

FtpWebRequest request = (FtpWebRequest)WebRequest.Create(ftpname);

要:

string remoteFileName = "δοκιμαστικό αρχείο - Copy.txt";
String ftpname = "ftp://ftp.myhost.gr/public_html/test" + @"/" + remoteFileName;

var escapedUriString = Uri.EscapeUriString(Encoding.UTF8.GetString(Encoding.ASCII.GetBytes(ftpname)));
var request = (FtpWebRequest)WebRequest.Create(escapedUriString);

这需要完成,因为EscapeUriString的输入参数是根据RFC 2396规范进行转义的。

RFC 2396标准声明:

  

当新的URI方案定义表示文本数据的组件时   由通用字符集[UCS]中的字符组成   首先应根据UTF-8将数据编码为八位字节   字符编码[STD63];然后只有那些没有的八位字节   对应于未保留集中的字符应该是   百分比编码

因此,上面显示的代码更改将强制此字符串以UTF-8格式输入。

关于:

  

2)为什么c#程序依赖于此设置?有特别的吗?   我应该遵循的方法,以避免依赖于此   设置?

Uri.EscapeUriString需要遵循RFC 2396规范的输入,因此需要以它理解的格式传递数据。