使用 Delphi 7 和 Indy 10 发送 UTF-8 编码响应

问题描述 投票:0回答:1

我需要使用 Indy 10 HTTP 服务器发送 UTF-8 编码的响应,其中包含特殊字符(如

ő
á
)。原来的程序是用Indy 9编写的,没有问题,但是根据Remy Lebeau的说法

在 Delphi 2009 之前的版本中,Indy 10 将在内部执行转换 如果指定 Ansi 和 Byte 编码,则从 AnsiString 到 UTF-16 到 Bytes 是不同的。在该转换期间,如果字节编码是 Indy8BitEncoding, U+00FF 以上的 UTF-16 代码单元将转换为“?”人物。 为了 要按原样发送 AnsiString,您必须设置 Ansi 和 Byte 编码 到同一个 TIdTextEncoding 对象。

但我找不到正确的方法。 HTTP 服务器的 IOHandler 没有 DefStringEncoding 属性,因此我尝试了以下对话,但没有成功:

        AResponseInfo.ContentEncoding:='utf8';
        AResponseInfo.ContentType:='text/html';

        ss:=TStringStream.Create('ő');
        ss.WriteString(' '+AnsiString('ő'));
        ss.WriteString(' '+WideString('ő'));
        ss.WriteString(' '+AnsiToUtf8('ő'));

        AResponseInfo.ContentText:=AResponseInfo.ContentText+ReadStringFromStream(ss, -1, IndyTextEncoding_8Bit, IndyTextEncoding_8Bit)+' ';
        ss.Seek(0, 0);
        AResponseInfo.ContentText:=AResponseInfo.ContentText+ReadStringFromStream(ss, -1, IndyTextEncoding_Default, IndyTextEncoding_8Bit)+' ';
        ss.Seek(0, 0);
        AResponseInfo.ContentText:=AResponseInfo.ContentText+ReadStringFromStream(ss, -1, IndyTextEncoding_ASCII, IndyTextEncoding_8Bit)+' ';
        ss.Seek(0, 0);
        AResponseInfo.ContentText:=AResponseInfo.ContentText+ReadStringFromStream(ss, -1, IndyTextEncoding_UTF16BE, IndyTextEncoding_8Bit)+' ';
        ss.Seek(0, 0);
        AResponseInfo.ContentText:=AResponseInfo.ContentText+ReadStringFromStream(ss, -1, IndyTextEncoding_UTF16LE, IndyTextEncoding_8Bit)+' ';
        ss.Seek(0, 0);
        AResponseInfo.ContentText:=AResponseInfo.ContentText+ReadStringFromStream(ss, -1, IndyTextEncoding_UTF7, IndyTextEncoding_8Bit)+' ';
        ss.Seek(0, 0);
        AResponseInfo.ContentText:=AResponseInfo.ContentText+ReadStringFromStream(ss, -1, IndyTextEncoding_UTF8, IndyTextEncoding_8Bit)+' ';

        ss.Seek(0, 0);
        AResponseInfo.ContentText:=AResponseInfo.ContentText+ReadStringFromStream(ss, -1, IndyTextEncoding_8Bit, IndyTextEncoding_UTF8)+' ';
        ss.Seek(0, 0);
        AResponseInfo.ContentText:=AResponseInfo.ContentText+ReadStringFromStream(ss, -1, IndyTextEncoding_Default, IndyTextEncoding_UTF8)+' ';
        ss.Seek(0, 0);
        AResponseInfo.ContentText:=AResponseInfo.ContentText+ReadStringFromStream(ss, -1, IndyTextEncoding_ASCII, IndyTextEncoding_UTF8)+' ';
        ss.Seek(0, 0);
        AResponseInfo.ContentText:=AResponseInfo.ContentText+ReadStringFromStream(ss, -1, IndyTextEncoding_UTF16BE, IndyTextEncoding_UTF8)+' ';
        ss.Seek(0, 0);
        AResponseInfo.ContentText:=AResponseInfo.ContentText+ReadStringFromStream(ss, -1, IndyTextEncoding_UTF16LE, IndyTextEncoding_UTF8)+' ';
        ss.Seek(0, 0);
        AResponseInfo.ContentText:=AResponseInfo.ContentText+ReadStringFromStream(ss, -1, IndyTextEncoding_UTF7, IndyTextEncoding_UTF8)+' ';
        ss.Seek(0, 0);
        AResponseInfo.ContentText:=AResponseInfo.ContentText+ReadStringFromStream(ss, -1, IndyTextEncoding_UTF8, IndyTextEncoding_UTF8)+' ';

我得到了以下回复:

? ? ??  ? ? ?? ??? ???  o o L'  ? ? ?  Aµ Aµ A.Â'  dz? dz? dz?dz?  dz? dz? dz?dz? ⃵⃵âƒ. d" d" e"   Aµ Aµ A.Â'  o o L' 

最接近的是

o
,但缺少重音。
L'
似乎也很有希望,因为
ő
是 UTF-8 字节中的
Ĺ‘
,但它也不完全相同。

我该如何解决这个问题?

更新

如果我将

AResponseInfo.CharSet
设置为
UTF-8
,然后将
ContentText
设置为 ANSI 中所需的字符串(不转换为任何内容),它就可以工作。

但现在我面临另一个问题,当我的

ContentText
已经是UTF-8时,Indy 10会尝试再次将其转换为UTF-8。因为我无法设置
DefStringEncoding
,因为它在这里不可用,所以我无法让 Indy 10 跳过对话。唯一的解决方法是将 UTF-8 字符串转换回 ANSI,然后让 Indy 再次将其转换为 UTF-8。

delphi utf-8 delphi-7 indy indy10
1个回答
1
投票

HTTP 服务器的 IOHandler 没有 DefStringEncoding 属性...我无法设置 DefStringEncoding,因为它在这里不可用

是的,可以使用。 它是连接

IOHandler
的属性,而不是服务器
IOHandler
的属性。

AResponseInfo.ContentType := 'text/html';
AResponseInfo.Charset := 'utf-8';
AResponseInfo.ContentText := Utf8Encode('ő');
AContext.Connection.IOHandler.DefStringEncoding := IndyTextEncoding_UTF8;
AContext.Connection.IOHandler.DefAnsiEncoding := IndyTextEncoding_UTF8;

话虽这么说,一个更简单的解决方案是将 UTF-8 内容放入

TStream
中,然后使用
AResponseInfo.ContentStream
而不是
AResponseInfo.ContentText

AResponseInfo.ContentType := 'text/html';
AResponseInfo.Charset := 'utf-8';
AResponseInfo.ContentStream := TStringStream.Create(Utf8Encode('ő'));
© www.soinside.com 2019 - 2024. All rights reserved.