delphi – POST响应的TIdHTTP字符编码

采取以下情况:
procedure Test;

var
 Response : String;

begin
 Response := IdHttp.Post(MyUrL,AStream);
 DoSomethingWith(Response);
end;

现在,web服务器以UTF-8返回数据.
假设它返回一些包含字符é的UTF-8 XML.
如果我使用变量Response它不包含这个字符,但它是UTF-8变种(#C3#A9),所以Indy没有解码?

现在我知道如何解决这个问题:

procedure Test;

var
 Response : String;

begin
 Response := UTF8ToString(IdHttp.Post(MyUrL,AStream));
 DoSomethingWith(Response);
end;

这个解决方案的一个警告:Delphi引发警告W1058(隐含的字符串转换,潜在的数据丢失从’string’到’RawByteString’)

我的问题:这是处理这个问题的正确方法,还是我可以指示TIdHTTP为我转换为UnicodeString?

解决方法

如果您使用的是Indy 10的最新版本,那么返回String的TIdHTTP.Post()的重载版本会将数据解码为Unicode,但用于解码的实际字符集取决于哪种媒体类型HTTP Content-Type响应头指定:

>如果媒体类型是application / xml,application / xml-external-parsed-entity,application / xml-dtd,或者不是text / …类型但以xml结尾,那么编码中指定的charset使用XML的prolog属性.如果未指定charset,则使用UTF-8.
>否则,如果Content-Type响应头指定了charset,则使用它.
>否则,如果媒体类型是text / …类型,则:

一个.如果媒体类型是text / xml,text / xml-external-parsed-entity,或以xml结尾,则使用us-ascii.

湾否则使用ISO-8859-1.
>否则,使用Indy的认编码(认为ASCII).

如果没有看到实际的HTTP Content-Type标头,很难知道您的情况属于哪种情况.听起来它落入#2或#3b,如果正在使用ISO-8859-1或类似的字符集,它将解释按原样返回的UTF-8字节值.

UTF8ToString()期望UTF-8编码的RawByteString作为输入,但您将传递UTF-16编码的UnicodeString.在这种情况下,RTL将执行UTF16-> Ansi转换,使用认的Ansi字符集进行转换.这就是您收到编译器警告的原因,因为这样的转换可能会丢失数据.

XML实际上是一种二进制数据格式,受charset编码的限制. XML解析器需要知道XML的编码是什么,并能够相应地解析原始编码的字节.这就是为什么XML在XML prolog中具有明确的编码属性.但是,当TIdHTTP将XML作为字符串下载时,虽然它会自动将其解码为Unicode,但它还没有相应地更新XML的序言.

真正的解决方案是首先不要将XML作为String下载.将其作为TStream下载(TMemoryStream是比TStringStream更好的选择),因此您的XML解析器可以访问原始字节,原始字符集声明等.例如,您可以将TStream传递给TXMLDocument.LoadFromStream()方法.

相关文章

 从网上看到《Delphi API HOOK完全说明》这篇文章,基本上都...
  从网上看到《Delphi API HOOK完全说明》这篇文章,基本上...
ffmpeg 是一套强大的开源的多媒体库 一般都是用 c/c+&#x...
32位CPU所含有的寄存器有:4个数据寄存器(EAX、EBX、ECX和ED...
1 mov dst, src dst是目的操作数,src是源操作数,指令实现的...