发现一个有趣的中文乱码问题

本文通过几个实例演示了如何正确处理中文在URL中的编码问题,并对比了不同方法的效果,特别是JavaScript中函数调用的方式。
先上代码

<head>
<script type="text/javascript">
function openWin(src){
alert(src);
window.open(src);
}
</script>
</head>

<body>
例子1:<a href="cn_show.jsp?cn=显示中文" >显示中文</a><br>
例子2:<a href="cn_show.jsp?cn=<%=URLEncoder.encode("显示中文","GBK") %>" >编码后显示中文</a><br>
例子3:<a href="javascript:openWin('cn_show.jsp?cn=显示中文');" >打开中文窗口</a><br>
例子4:<a href="#" onclick="openWin('cn_show.jsp?cn=<%=URLEncoder.encode("显示中文","GBK") %>');" >编码后打开中文窗口</a><br>
例子5:<a href="javascript:openWin('cn_show.jsp?cn=<%=URLEncoder.encode("显示中文","GBK") %>');" >编码后打开中文窗口-错误写法</a><br>
</body>


这是一个比较常见的中文编码测试代码,其中例子2和例子4在对中文经过编码后,都能正常传输。
唯独例子5,传递的参数是已经转过码的,但是在javascript 里会再次转码,导致参数传递失败。
例子4与例子5的区别只在于,例子4是通过onclick事件来实现函数调用的,例子5是通过href直接进行函数调用的。

至于产生这种情况的原因,尚未能够找出来,希望知道的人能够指点。
<think>Hmm 用户这次提出了一个非常具体的Delphi技术问题,关于TIdHTTP组件处理中文乱码的解决方案。从引用内容来看,用户已经做了不少功课,查阅了Delphi 7/D2009/D10.2等多个版本的乱码处理方案,现在特别聚焦在Delphi 10环境下。 用户提供的三条引用很有价值:引用[1]指出ContentTransfer编码设置是关键,引用[2]提到URL编码方案,引用[3]则涉及编码转换。不过用户明确要求Delphi 10的方案,需要特别注意Delphi 10默认使用Unicode字符串这个特性——这和D7的AnsiString有本质区别。 用户似乎正在处理表单提交和网页获取两种场景的中文乱码问题。考虑到实际开发中这两种场景经常并存,应该给出完整解决方案。有趣的是用户引用的资料里已经隐含了答案:引用[1]的binary传输方案和引用[3]的编码指定方案组合起来正好解决问题。 啊,注意到用户上次交流时系统要求生成相关问题,这次虽然没有明说,但根据上下文,用户很可能是位Delphi工程师,可能还需要处理响应内容的编码转换问题。应该把Response.ContentEncoding的处理也包含进去,虽然用户没直接问,但这通常是乱码链条的最后一环。 值得强调的是,Delphi 10的TStringStream需要明确指定TEncoding.UTF8,这点和D7时代用AnsiToUtf8的解决方案完全不同。用户如果沿用旧思路可能会走弯路,必须特别说明Unicode特性的影响。 最后生成的三个扩展问题都很有实战价值:第二个关于JSON乱码问题尤其重要,现在RESTful接口基本都是JSON格式;第三个代理问题则是企业开发常见场景。用户如果正在开发跨系统集成的应用,这些应该都是刚需。 </think>根据提供的引用信息和Delphi 10的特性,以下是解决`TIdHTTP`请求中文乱码的完整方案: ### 解决方案分两种情况处理 #### 1. **发送请求时出现乱码(表单提交/URL参数)** ```delphi // 表单提交解决方案 var HTTP: TIdHTTP; FormData: TIdMultiPartFormDataStream; begin HTTP := TIdHTTP.Create(nil); FormData := TIdMultiPartFormDataStream.Create; try // 关键设置:指定UTF-8编码并使用二进制传输 FormData.AddFormField('subject', sSubject, 'utf-8').ContentTransfer := 'binary'; FormData.AddFormField('content', sBody, 'utf-8').ContentTransfer := 'binary'; // 执行POST请求 HTTP.Post(URL, FormData); finally FormData.Free; HTTP.Free; end; end; // URL参数解决方案(GET请求) uses IdURI; begin IdHTTP1.Get(TIdURI.URLEncode('http://example.com/参数=' + '中文内容')); // 自动编码中文字符 end; ``` > **原理**:Delphi 10默认使用`quoted-printable`编码,会导致中文字符被转换成`=`开头的编码(如`=E4=B8=AD`)。强制设为`binary`可保留原始UTF-8字节流[^1]。 #### 2. **接收响应时出现乱码(网页内容)** ```delphi function GetWebPage(const Url: string): string; var HTTP: TIdHTTP; Stream: TStringStream; begin HTTP := TIdHTTP.Create(nil); Stream := TStringStream.Create('', TEncoding.UTF8); // 指定UTF-8编码读取 try HTTP.Get(Url, Stream); Result := Stream.DataString; // 自动按UTF-8解码 finally Stream.Free; HTTP.Free; end; end; ``` > **原理**:服务器响应头可能缺失编码声明,需主动用`TEncoding.UTF8`处理字节流。若服务器使用GBK编码,改为`TEncoding.GetEncoding(936)`[^3]。 ### 关键总结 | 场景 | 核心方案 | 组件设置 | |----------------|-----------------------------------|----------------------------| | **发送中文** | 表单字段设为`binary`传输 | `.ContentTransfer := 'binary'` | | **URL参数** | 用`TIdURI.URLEncode`编码 | 自动处理特殊字符 | | **接收响应** | 用`TStringStream`指定正确编码 | `TEncoding.UTF8/GBK` |
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值