ftp 创建一个带有 utf-8 字符的文件名,例如希腊语、德语等



我正在尝试使用以下代码为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# 程序依赖于此设置?我应该遵循某种特殊方法以避免依赖此设置吗?

编码噩梦再次出现:(

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

为了使这一切正常工作,您(您的程序)必须首先检查您的服务器的功能。服务器在客户端连接后发送其功能 - 在您的情况下,您必须检查 FEAT UTF8。如果您的服务器发送该消息 - 这意味着它理解 UTF8。尽管如此 - 即使它理解它 - 你必须明确告诉它,从现在开始,你将发送你的文件名UTF8编码,现在它是你的程序缺乏的东西(因为你的服务器支持utf8,正如你所说)。

您的客户端必须将以下 OPTS UTF8 打开发送到 FTP 服务器。发送后,您可以使用 UTF8 或对您的服务器说 UTF8-ish(可以这么说)。

阅读此处了解文件传输协议国际化的详细信息

在您的代码更改中:

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 格式输入此字符串。

关于:

  1. 为什么 C# 程序依赖于此设置?有没有特别的我应该遵循的方法,以避免依赖这一点设置?

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

最新更新