indy httpserver 接收URL包含中文参数乱码的问题
2016-07-06 23:53
411 查看
在测试TIdHttpServer的时候,发现浏览器提交的URL包含中文时会乱码,我用的是XE7 UPDATE1,INDY是10。
procedure TForm1.idhtpsrv1CommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo;
AResponseInfo: TIdHTTPResponseInfo);
在这事件处理中文时,AResponseInfo好办,只要设置下
AResponseInfo.ContentType := 'text/html';
AResponseInfo.CharSet := 'utf-8';
浏览器就能正确显现中文。
对于 ARequestInfo,回头想想一开始决解方向就错了,不要想着各种编码转换,实际到这里,INDY已经把编码转换好了,因为到这里处理的文本,
ARequestInfo.Params.Text已经是string类型了(UNICODE)。网上说是改INDY的源码,因为没地方设置TIdHTTPRequestInfo编码属性。
改动的是IdCustomHTTPServer.pas的 TIdHTTPRequestInfo.DecodeAndSetParams(const AValue: String)方法:
procedure TIdHTTPRequestInfo.DecodeAndSetParams(const AValue: String);
var
i, j : Integer;
s: string;
LEncoding: IIdTextEncoding;
begin
// Convert special characters
// ampersand '&' separates values {Do not Localize}
Params.BeginUpdate;
try
Params.Clear;
CharSet := 'utf-8'; //添加这一行
// which charset to use for decoding query string parameters. We
// should not be using the 'Content-Type' charset for that. For
// 'application/x-www-form-urlencoded' forms, we should be, though...
LEncoding := CharsetToEncoding(CharSet);
i := 1;
while i <= Length(AValue) do
begin
j := i;
while (j <= Length(AValue)) and (AValue[j] <> '&') do {do not localize}
begin
Inc(j);
end;
s := Copy(AValue, i, j-i);
// See RFC 1866 section 8.2.1. TP
s := StringReplace(s, '+', ' ', [rfReplaceAll]); {do not localize}
Params.Add(TIdURI.URLDecode(s, LEncoding));
i := j + 1;
end;
finally
Params.EndUpdate;
end;
end;
然后重新编译IndyProtocols包,注意bpl文件放在bin下,dcu和dcp文件放在Lib下的各个相应目录下(就是win32/win64, debug/release)
测试代码:
procedure TForm1.idhtpsrv1CommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo;
AResponseInfo: TIdHTTPResponseInfo);
begin
AResponseInfo.ContentType := 'text/html';
AResponseInfo.CharSet := 'utf-8';
mmo1.Lines.Add('=====================');
mmo1.Lines.Add('Document:');
mmo1.Lines.Add('');
mmo1.Lines.Add(ARequestInfo.Params.Text);
mmo1.Lines.Add('p1: '+ ARequestInfo.Params.Values['p1']);
mmo1.Lines.Add('p2: '+ ARequestInfo.Params.Values['p2']);
AResponseInfo.ContentText := '是中文吧'; // 'HttpServer OK';
end;
浏览器URL:http://127.0.0.1:8000/test?p1=中文&p2=ghg
用 Chrome,edge,360浏览器测试正确。
procedure TForm1.idhtpsrv1CommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo;
AResponseInfo: TIdHTTPResponseInfo);
在这事件处理中文时,AResponseInfo好办,只要设置下
AResponseInfo.ContentType := 'text/html';
AResponseInfo.CharSet := 'utf-8';
浏览器就能正确显现中文。
对于 ARequestInfo,回头想想一开始决解方向就错了,不要想着各种编码转换,实际到这里,INDY已经把编码转换好了,因为到这里处理的文本,
ARequestInfo.Params.Text已经是string类型了(UNICODE)。网上说是改INDY的源码,因为没地方设置TIdHTTPRequestInfo编码属性。
改动的是IdCustomHTTPServer.pas的 TIdHTTPRequestInfo.DecodeAndSetParams(const AValue: String)方法:
procedure TIdHTTPRequestInfo.DecodeAndSetParams(const AValue: String);
var
i, j : Integer;
s: string;
LEncoding: IIdTextEncoding;
begin
// Convert special characters
// ampersand '&' separates values {Do not Localize}
Params.BeginUpdate;
try
Params.Clear;
CharSet := 'utf-8'; //添加这一行
// which charset to use for decoding query string parameters. We
// should not be using the 'Content-Type' charset for that. For
// 'application/x-www-form-urlencoded' forms, we should be, though...
LEncoding := CharsetToEncoding(CharSet);
i := 1;
while i <= Length(AValue) do
begin
j := i;
while (j <= Length(AValue)) and (AValue[j] <> '&') do {do not localize}
begin
Inc(j);
end;
s := Copy(AValue, i, j-i);
// See RFC 1866 section 8.2.1. TP
s := StringReplace(s, '+', ' ', [rfReplaceAll]); {do not localize}
Params.Add(TIdURI.URLDecode(s, LEncoding));
i := j + 1;
end;
finally
Params.EndUpdate;
end;
end;
然后重新编译IndyProtocols包,注意bpl文件放在bin下,dcu和dcp文件放在Lib下的各个相应目录下(就是win32/win64, debug/release)
测试代码:
procedure TForm1.idhtpsrv1CommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo;
AResponseInfo: TIdHTTPResponseInfo);
begin
AResponseInfo.ContentType := 'text/html';
AResponseInfo.CharSet := 'utf-8';
mmo1.Lines.Add('=====================');
mmo1.Lines.Add('Document:');
mmo1.Lines.Add('');
mmo1.Lines.Add(ARequestInfo.Params.Text);
mmo1.Lines.Add('p1: '+ ARequestInfo.Params.Values['p1']);
mmo1.Lines.Add('p2: '+ ARequestInfo.Params.Values['p2']);
AResponseInfo.ContentText := '是中文吧'; // 'HttpServer OK';
end;
浏览器URL:http://127.0.0.1:8000/test?p1=中文&p2=ghg
用 Chrome,edge,360浏览器测试正确。
相关文章推荐
- 创建httpd启动脚本并加入启动列表开机启动
- TCP和UDP通信
- Android网络框架源码分析一----Volley
- Qt---基于UDP的网络广播程序
- udp与tcp通信代码
- HTTP协议
- HTTP Servlet 重要的几个方法
- 学习TensorFlow,TensorBoard可视化网络结构和参数
- 学习TensorFlow,TensorBoard可视化网络结构和参数
- UNIX网络编程——shutdown函数(I/O复用并发服务器)
- 使用 acl 协程编写高并发网络服务
- WiFi时,显示图片高清图;网络状态为蜂窝移动网络时,显示图片缩略图http://gold.xitu.io/entry/57285c5e2e958a0068db2f9e
- AJAX入门 之 XMLHttpRequest 状态与 onreadystatechange 事件(三)
- 使用WebService进行网络编程【工具类】
- Linux下的C语言开发(网络编程)
- Qt---获取本机网络信息
- 学习笔记——网络基础(一)
- wifi eth gprs 网络自动切换 脚本
- 通过HttpServletRequest获取上一个页面
- HTTP中GET和POST的区别