首页 > 解决方案 > 使用 Indy 10 接收 Unicode 字符串

问题描述

我正在使用最新的 Delphi 10.4.2 和 Indy 10。

在 REST 服务器中,接收和处理 JSON 命令。它工作正常,除了 Unicode。

像这样的简单 JSON:

{"driverNote": "Test"}

正确显示

图片

如果我现在更改为 Unicode 俄罗斯字符:

{"driverNote": "Статья"}

图片

不知道我应该从哪里开始跟踪这个。我希望ARequestInfo.FormParams在调试器中具有与变量相同的值s

如果我调试 Indy 本身,FormParams则在此代码中设置:

if LRequestInfo.PostStream <> nil then
begin
  // decoding percent-encoded octets and applying the CharSet is handled by
  // DecodeAndSetParams() further below...
  EnsureEncoding(LEncoding, enc8Bit);
  LRequestInfo.FormParams := 
    ReadStringFromStream( LRequestInfo.PostStream, 
                          -1, 
                          LEncoding
                          {$IFDEF STRING_IS_ANSI}, LEncoding{$ENDIF});
  DoneWithPostStream(AContext, LRequestInfo); // don't need the PostStream anymore
end;

它使用enc8Bit. 但我的字符串有 16 位字符。

这在 Indy 中处理不正确吗?

标签: delphiunicodeindyindy10delphi-10.4-sydney

解决方案


您引用的代码片段IdCustomHTTPServer.pas不是 Indy 的GitHub 存储库中的代码片段。

在官方代码中,TIdHTTPServer不解码PostStreamtoFormParams除非ContentType'application/x-www-form-urlencoded'

if LRequestInfo.PostStream <> nil then begin
  if TextIsSame(LContentType, ContentTypeFormUrlencoded) then
  begin
    // decoding percent-encoded octets and applying the CharSet is handled by DecodeAndSetParams() further below...
    EnsureEncoding(LEncoding, enc8Bit);
    LRequestInfo.FormParams := ReadStringFromStream(LRequestInfo.PostStream, -1, LEncoding{$IFDEF STRING_IS_ANSI}, LEncoding{$ENDIF});
    DoneWithPostStream(AContext, LRequestInfo); // don't need the PostStream anymore
  end;
end;

ContentType检查是在 2010 年添加的,所以我不知道为什么它没有出现在您的版本中。

在您的示例中,ContentTypeis 'application/json',因此原始 JSON应该在中PostStream并且FormParams 应该是空白的。

话虽这么说,在您的 Indy 版本中,TIdHTTPServer只是从 中读取原始字节PostStream并将每个字节零扩展为FormParams. 要恢复原始字节,只需将每个字节截断Char为 8 位Byte. 例如,您可以在单元中使用 Indy 的ToBytes()函数,将/指定为字节编码。IdGlobalenc8BitIndyTextEncoding_8Bit

JSON 最常以 UTF-8 传输(在您的示例中就是这种情况),因此当您可以访问任何版本的原始字节时,请确保将 JSON 字节解析为 UTF-8。


推荐阅读