delphi - POST 响应的 TIdHTTP 字符编码

标签 delphi unicode utf-8 delphi-xe idhttp

采取以下情况:

procedure Test;

var
 Response : String;

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

现在网络服务器以 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 响应 header 指定的媒体类型:

  1. 如果媒体类型是 application/xmlapplication/xml-external-parsed-entityapplication/xml-dtd code>,或者不是 text/... 类型,但以 +xml 结尾,则在 encoding 属性中指定的字符集使用 XML 的序言。如果未指定字符集,则使用 UTF-8。

  2. 否则,如果 Content-Type 响应 header 指定了字符集,则使用它。

  3. 否则,如果媒体类型是 text/... 类型,则:

    a.如果媒体类型为 text/xmltext/xml-external-parsed-entity 或以 +xml 结尾,则 使用 us-ascii

    b.否则使用 ISO-8859-1

  4. 否则,将使用 Indy 的默认编码(默认为 ASCII)。

如果没有看到实际的 HTTP Content-Type header ,就很难知道您的情况属于哪种情况。听起来它属于 #2 或 #3b,如果使用 ISO-8859-1 或类似的字符集,这将说明按原样返回 UTF-8 字节值。

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

XML 实际上是一种二进制数据格式,受字符集编码的约束。 XML 解析器需要知道 XML 的编码是什么,并能够相应地解析原始编码字节。这就是为什么 XML 在 XML 序言中具有显式的 encoding 属性。但是,当 TIdHTTP 将 XML 作为 String 下载时,尽管它会自动将其解码为 Unicode,但它不会相应地更新 XML 的序言。

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

关于delphi - POST 响应的 TIdHTTP 字符编码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18832081/

相关文章:

multithreading - 如何防止卡住MainForm并等待子线程的返回值

java - 使用 Unicode 文件路径

python - 在参数中使用带有 unicode 字符的 {% url %} 反向 (Django)

PHP:html_entity_decode 删除/不显示字符

php - 在 php 中用于俄语的 mb_convert_encoding

delphi - 如何查询 Delphi 组件面板?

delphi - 如何在 Spring4d 中创建和使用不区分大小写的 IList<string>

delphi - 在窗体中创建 Delphi 对象

.net - 代理对检测失败

java - 在php中将字符串转换为utf-8