我正在尝试使用以下代码为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#程序依赖于此设置?我是否应遵循特殊的方法以避免依赖此设置?
再次出现编码噩梦:(
答案 0 :(得分:8)
仅仅将字符串编码为UTF8并将其作为文件名发送到FTP服务器是不够的。在过去,所有FTP服务器都只理解ASCII,现在为了保持向后兼容性 - 即使它们是Unicode识别的 - 当它们启动时它们也将所有文件也视为ASCII。
要使一切顺利,您(您的程序)必须首先检查您的服务器能够做什么。客户端连接后服务器发送其功能 - 在您的情况下,您必须检查 FEAT UTF8 。如果你的服务器发送 - 它意味着它理解UTF8。尽管如此 - 即使它理解它 - 您必须明确告诉它,从现在开始,您将发送您的文件名UTF8编码,现在它是您的程序缺少的东西(因为您的服务器支持utf8,如您所述)。
您的客户必须向FTP服务器发送以下 OPTS UTF8 ON 。发送后你可以使用UTF8或者说你的服务器UTF8-ish(可以这么说)。
答案 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规范的输入,因此需要以它理解的格式传递数据。