Delphi XE + Indy 10中TIdHTTP调用WebService的特殊撇号编码问题
解决Delphi XE + Indy 10调用WebService时的特殊字符编码问题
我之前踩过类似的Indy编码坑,你的问题核心是字符集不匹配导致参数被双重编码——你预期发送的是Bev%E2%80%99s(U+2019弯撇号的正确UTF-8 URL编码),但WebService收到的Bev%C3%A2%C2%80%C2%99s,本质是Indy先把Unicode字符用错误的字符集转成了字节,再做了URL编码,相当于把UTF-8字节又当成Latin1字符重新编码了一遍。
解决步骤:
先明确:
hoForceEncodeParams确实会强制Indy对URL参数进行编码,但Indy默认使用的字符集不是UTF-8(通常是ASCII或系统默认编码),这才是问题根源。你需要手动指定UTF-8作为请求的字符集,让Indy用正确的编码处理参数。修改你的代码,添加字符集配置:
idHttp.ConnectTimeOut := iTimeOut; idhttp.HTTPOptions := [hoForceEncodeParams]; // 关键:指定请求的字符集为UTF-8,确保参数编码时使用UTF-8 idHTTP.Request.CharSet := 'utf-8'; // 如果是POST请求,还要给Content-Type加上字符集声明 idHTTP.Request.ContentType := 'application/x-www-form-urlencoded; charset=utf-8';额外注意:不要手动提前对参数做URL编码!如果你自己先把
Bev’s转成Bev%E2%80%99s再传给Indy,hoForceEncodeParams会把%也编码成%25,导致三重编码,反而让问题更糟。备选方案(手动编码参数):
如果你更倾向于自己控制编码过程,可以关闭hoForceEncodeParams,用TIdURI.ParamsEncode指定UTF-8编码来处理参数,再拼接URL:var LParam, LURL: string; begin LParam := 'Bev’s'; // 用UTF-8编码对参数做URL编码 LParam := TIdURI.ParamsEncode(LParam, IndyTextEncoding_UTF8); LURL := 'http://your-webservice-endpoint?yourParam=' + LParam; idHttp.ConnectTimeOut := iTimeOut; idhttp.HTTPOptions := []; // 关闭自动编码,避免重复处理 idHTTP.Request.CharSet := 'utf-8'; idHTTP.Get(LURL); end;
验证方法:
可以用Indy自带的TIdLogDebug组件或者第三方抓包工具查看实际发送的请求,确认参数是Bev%E2%80%99s,而不是被重复编码的版本。
内容的提问来源于stack exchange,提问作者M Schenkel




