具有编码UTF8的IdHTTPServer和IdHTTP

时间:2018-02-13 17:35:15

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

我正在使用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

任何人都可以帮助我吗?

1 个答案:

答案 0 :(得分:3)

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

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

您必须确保仅将有效的网址编码网址传递给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;