3

我有一个使用以下代码监听端口 8844 的 TidHttpServer:

procedure TForm1.IdHTTPServer1CommandGet(AContext: TIdContext;
  ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
begin
  if ARequestInfo.Document <> '/favicon.ico' then
  begin
    Memo1.Text := ARequestInfo.Params.Text;
  end;
end;

这是用 Delphi XE2 编译的。当我浏览到

http://localhost:8844/document?Value=%F6   <-- %F6 is the encoded value for ö

...我得到了结果:

value=?

如果我使用 Delphi 2007 编译应用程序,我会得到以下结果

value=ö

这是印地中我错过的东西的错误吗?

4

1 回答 1

5

在 XE2 中,字符串是 Unicode。在D2009 及更高版本中TIdHTTPServer解码ARequestInfo.Document时,需要将百分比编码的数据解码为 UTF-8 编码的数据,然后将其解码为最终的 Unicode 字符串。目前没有选项可以改变它(我已经向我们的问题跟踪器提交了一个功能请求)。 %F6不代表有效的 UTF-8 八位字节,这就是您最终得到'?'. 在 UTF-8 中,'ö'字符将被 UTF-8 编码为$C3 $B6,因此百分比编码为%C3%B6,而不是%F6

在 D2007 中,字符串是 Ansi。在D2007 及更早版本中TIdHTTPServer解码ARequestInfo.Document时,它按原样提供解码数据,因此%F6将解码$F6并存储为#246. 然后,RTL 会使用本地机器的默认 Ansi 代码页来解释该值,因此它将'ö'仅代表以这种方式定义它的 Ansi 代码页的字符(Windows-1252 和 ISO-8859-1 可以,但 ISO-8859-例如,5 没有)。

我建议您更改服务器逻辑以在两个 Delphi 版本中使用 UTF-8 编码的 URL。在 D2007 中,您可以使用 RTL 的UTF8Decode()函数将编码AnsiString为的 UTF-8 解码WideString,然后您可以将其分配给另一个AnsiString以将数据转换为您最初期望的 Ansi 值。在 D009+ 中,它会自动为您处理。

附带说明一下,直接在OnCommandGet事件中访问 UI 组件不是线程安全的。您必须与主线程同步才能安全地访问 UI。

于 2012-10-11T19:57:49.710 回答