【问题标题】:IdHTTPServer and IdHTTP with Encoding UTF8使用 UTF8 编码的 IdHTTPServer 和 IdHTTP
【发布时间】:2018-07-24 03:51:46
【问题描述】:

我正在使用TIdHTTPServerTIdHTTP 测试本地主机服务器。我在编码 UTF8 数据时遇到问题。

客户端:

procedure TForm1.SpeedButton1Click(Sender: TObject);
var
  res: string;
begin
  res:=IdHTTP1.Get('http://localhost/?msg=đi chơi thôi');
  Memo1.Lines.Add(res);
end;

服务器端:

procedure TForm1.OnCommandGet(AContext: TIdContext;
  ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
begin
  Memo1.Lines.Add(ARequestInfo.Params.Values['msg']); // ?i ch?i th?i

  AResponseInfo.CharSet := 'utf-8';
  AResponseInfo.ContentText := 'chào các bạn'; // chào các b?n
end;

我想发送đi chơi thôi 并接收chào các bạn。但是服务器接收?i ch?i th?i,客户端接收chào các b?n

谁能帮帮我?

【问题讨论】:

    标签: delphi utf-8 indy delphi-xe7 indy10


    【解决方案1】:

    TIdHTTP 完全按照您提供的方式传输 URL,但 http://localhost/?msg=đi chơi thôi 不是可以按原样传输的有效 URL,因为 URL 只能包含 ASCII 字符。未保留的 ASCII 字符可以按原样使用,但保留和非 ASCII 字符必须以字符集编码为字节,然后这些字节必须以%HH 格式进行 url 编码,例如:

    IdHTTP1.Get('http://localhost/?msg=%C4%91i%20ch%C6%A1i%20th%C3%B4i');
    

    您必须确保仅将有效的 url 编码 URL 传递给 TIdHTTP

    在此示例中,URL 是硬编码的,但如果您需要更动态的内容,请使用 TIdURI 类,例如:

    IdHTTP1.Get('http://localhost/?msg=' + TIdURI.ParamsEncode('đi chơi thôi'));
    

    TIdHTTPServer 然后将按照您的预期解码参数数据。 TIdURITIdHTTPServer 默认使用 UTF-8。

    发送响应时,您只是设置了CharSet,但没有设置ContentType。所以TIdHTTPServer 会将ContentType 设置为'text/html; charset=ISO-8859-1',覆盖你的CharSet。您需要自己显式设置ContentType,以便您可以指定自定义CharSet,例如:

    AResponseInfo.ContentType := 'text/plain';
    AResponseInfo.CharSet := 'utf-8';
    AResponseInfo.ContentText := 'chào các bạn';
    

    或者:

    AResponseInfo.ContentType := 'text/plain; charset=utf-8';
    AResponseInfo.ContentText := 'chào các bạn';
    

    附带说明,TIdHTTPServer 是一个多线程组件。 OnCommand... 事件在工作线程的上下文中触发,而不是在主 UI 线程中触发。所以像你一样直接访问Memo1 不是线程安全的。您必须与主 UI 线程同步才能安全地访问 UI 控件,例如:

    procedure TForm1.OnCommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
    var
      msg: string;
    begin
      msg := ARequestInfo.Params.Values['msg'];
      TThread.Synchronize(nil,
        procedure
        begin
          Memo1.Lines.Add(msg);
        end
      );
      ...
    end;
    

    【讨论】:

    • 您好 Remy,今天我正在调查内部使用 Indy 的第 3 方库的类似问题...我认为您在此处发布的解决方案(提供 CharSet ContentType 的值)应该也适用于异常处理中的 TIdCustomHTTPServer.DoExecute,因为如果异常消息是远东语言(非 ASCII),响应文本也会混乱。
    • @EdwinYip 谢谢,我有空的时候会研究一下。同时,我有opened a ticket 为它服务
    • 抱歉,如果请求以 UTF-8 格式发送,我仍然不明白如何在 POST 请求中获取正确的 Unicode 参数值。
    • @Paul 你不明白什么?我以为我很清楚需要什么。您遇到的实际问题是什么?也许发布一个关于它的新问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-07
    • 1970-01-01
    • 1970-01-01
    • 2012-06-19
    • 1970-01-01
    相关资源
    最近更新 更多