IdHTTPServer 和编码为 UTF8 的 IdHTTP
IdHTTPServer and IdHTTP with Encoding UTF8
我正在使用 TIdHTTPServer
和 TIdHTTP
测试本地主机服务器。我在编码 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
.
谁能帮帮我?
TIdHTTP
完全按照您提供的方式传输 URL,但是 http://localhost/?msg=đi chơi thôi
不是可以按原样传输的有效 URL,因为 URLs 只能包含 ASCII 字符。未保留的 ASCII 字符可以按原样使用,但保留和非 ASCII 字符必须被字符集编码为字节,然后这些字节必须被 url 编码为 %HH
格式,例如:
IdHTTP1.Get('http://localhost/?msg=%C4%91i%20ch%C6%A1i%20th%C3%B4i');
您必须确保仅将有效的 url 编码的 URL 传递给 TIdHTTP
。
在此示例中,URL 是硬编码的,但如果您需要更动态的内容,请使用 TIdURI
class,例如:
IdHTTP1.Get('http://localhost/?msg=' + TIdURI.ParamsEncode('đi chơi thôi'));
TIdHTTPServer
将按照您的预期解码参数数据。 TIdURI
和 TIdHTTPServer
默认都使用 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;
我正在使用 TIdHTTPServer
和 TIdHTTP
测试本地主机服务器。我在编码 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
.
谁能帮帮我?
TIdHTTP
完全按照您提供的方式传输 URL,但是 http://localhost/?msg=đi chơi thôi
不是可以按原样传输的有效 URL,因为 URLs 只能包含 ASCII 字符。未保留的 ASCII 字符可以按原样使用,但保留和非 ASCII 字符必须被字符集编码为字节,然后这些字节必须被 url 编码为 %HH
格式,例如:
IdHTTP1.Get('http://localhost/?msg=%C4%91i%20ch%C6%A1i%20th%C3%B4i');
您必须确保仅将有效的 url 编码的 URL 传递给 TIdHTTP
。
在此示例中,URL 是硬编码的,但如果您需要更动态的内容,请使用 TIdURI
class,例如:
IdHTTP1.Get('http://localhost/?msg=' + TIdURI.ParamsEncode('đi chơi thôi'));
TIdHTTPServer
将按照您的预期解码参数数据。 TIdURI
和 TIdHTTPServer
默认都使用 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;