原链接:原链接
问题 (Question)
This code starts a HTTP server which listens for requests on port 8080. When compiled with Delphi 2009, the Chinese text is rendered correctly. With Free Pascal 2.6.0 however, the browser displays ä¸æ–‡
instead of 中文
.
What is the correct way to write Unicode / UTF-8 HTTP responses with Indy and Free Pascal?
这段代码启动HTTP服务器在端口8080上侦听请求。在Delphi 2009中编译时,中文文本正确呈现。然而,与自由帕斯卡2.6.0浏览器显示ä¸æ–‡
而不是中文
.
正确的方法是什么写Unicode utf - 8 / HTTP响应与印第安纳·琼斯和帕斯卡有空吗?
program IdHTTPUnicode;
{$APPTYPE CONSOLE}
uses
IdHTTPServer, IdCustomHTTPServer, IdContext, IdSocketHandle, IdGlobal,
SysUtils;
type
TMyServer = class (TIdHTTPServer)
public
procedure InitComponent; override;
procedure DoCommandGet(AContext: TIdContext;
ARequestInfo: TIdHTTPRequestInfo;
AResponseInfo: TIdHTTPResponseInfo); override;
end;
procedure Demo;
var
Server: TMyServer;
begin
Server := TMyServer.Create(nil);
try
try
Server.Active := True;
except
on E: Exception do
begin
WriteLn(E.ClassName + ' ' + E.Message);
end;
end;
WriteLn('Hit any key to terminate.');
ReadLn;
finally
Server.Free;
end;
end;
procedure TMyServer.InitComponent;
var
Binding: TIdSocketHandle;
begin
inherited;
Bindings.Clear;
Binding := Bindings.Add;
Binding.IP := '127.0.0.1';
Binding.Port := 8080;
Binding.IPVersion := Id_IPv4;
end;
procedure TMyServer.DoCommandGet(AContext: TIdContext;
ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
const
UNI = '中文';
begin
AResponseInfo.ContentText := '<html>' + UNI + '</html>';
AResponseInfo.ContentType := 'text/html';
AResponseInfo.CharSet := 'UTF-8';
end;
begin
Demo;
end.
procedure TIdIOHandler.Write(const AOut: string; AByteEncoding: TIdTextEncoding = nil
{$IFDEF STRING_IS_ANSI}; ASrcEncoding: TIdTextEncoding = nil{$ENDIF}
);
begin
if AOut <> '' then begin
AByteEncoding := iif(AByteEncoding, FDefStringEncoding);
{$IFDEF STRING_IS_ANSI}
ASrcEncoding := iif(ASrcEncoding, FDefAnsiEncoding, encOSDefault);
{$ENDIF}
Write(
ToBytes(AOut, -1, 1, AByteEncoding
{$IFDEF STRING_IS_ANSI}, ASrcEncoding{$ENDIF}
)
);
end;
end;
FreePascal字符串是utf - 16编码不像他们在Delphi 2009 +。FreePascal,在Delphi 2007和以前的版本中,您的代码需要考虑实际的字符串编码。这就是为什么赛车公开其他Ansi-based参数/属性为这些平台。
当TIdHTTPServer写出ContentText使用TIdIOHandler.Write(),ASrcEncoding参数没有使用unicode平台上,所以你必须使用TIdIOHandler.DefAnsiEncoding财产而不是让Write()知道的编码ContentText如:
procedure TMyServer.DoCommandGet(AContext: TIdContext;
ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
const
UNI: WideString = '中文';
begin
AResponseInfo.ContentText := UTF8Encode('<html>' + UNI + '</html>');
AResponseInfo.ContentType := 'text/html';
// this tells TIdHTTPServer what to encode bytes to during socket transmission
AResponseInfo.CharSet := 'utf-8';
// this tells TIdHTTPServer what encoding the ContentText is using
// so it can be decoded to Unicode prior to then being charset-encoded
// for output. If the input and output encodings are the same, the
// Ansi string data gets transmitted as-is without decoding/reencoding...
AContext.Connection.IOHandler.DefAnsiEncoding := IndyUTF8Encoding;
end;
在现代FreePascal默认字符串是utf - 8,除非你调整copil选项。
因此似乎在iif(ASrcEncoding, FDefAnsiEncoding, encOSDefault);
的价值encOSDefault
是错误的。你可以解决它的检测在印第安纳·琼斯来源如果你喜欢或我想更好的设置DefAnsiEncoding := 'utf-8';
(由RFC拖欠的低)
在安全方面你可以检查utf - 8模式在程序开始。设置一些非拉丁常数(如中国的事情,或希腊或斯拉夫字母——不管)和检查如果是UTF8:http://compaspascal.blogspot.ru/2009/03/utf-8-automatic-detection.html
不过总的来说,我认为你可能会发现一些库,关心FPC和Linux比印第安纳·琼斯。印地赛车似乎我停滞不前,甚至遗弃在Delphi旁边。也许Synopse mORMot
(寻找DataSnap性能测试文章)可以帮助你或者一些附带的库CodeTyphon
发行版。