Board logo

标题: 深入分析 web 请求响应中的编码问题(2)解决乱码的关键因素之客户端 [打印本页]

作者: look_w    时间: 2018-11-21 19:32     标题: 深入分析 web 请求响应中的编码问题(2)解决乱码的关键因素之客户端

解决乱码的关键因素之客户端web                页面HTML                meta data 中的 charset<meta http-equiv="Content-Type" content="text/html;                charset=UTF-8">
这里 charset 的作用有二点:
JSP page 命令中的 charset 与 pageEncoding<%@ page language="java" contentType="text/html; charset=GB18030"                pageEncoding="UTF-8"%>
浏览器通过地址栏发起的 Get                请求针对 get 请求的乱码容易出现在两个地方,一是请求的资源名称,二是查询参数。更复杂的是,不同的浏览器可能使用两种编码分别处理 URL                和查询参数。
表 1 列举了三种常见浏览器的编码情况:
表 1.                    三种常见浏览器对地址栏 URL 和查询参数的编码方式浏览器默认                                URI                                编默认查询参数编码 英文 Chrome 54  UTF-8  UTF-8  英文 Firefox 51  UTF-8  UTF-8  英文 IE 11  UTF-8  跟随系统 code page
其中 IE 11 中有如下设置:
默认按 UTF-8 发送 URL 路径 开启(设为 false 时按系统 code page 编码 URL 路径)
默认按 UTF-8 为内网 URL 发送查询字符串 关闭默认按 UTF-8 为外网 URL 发送查询字符串 关闭对 URL path                的设定工作正常,对 query string 的设定有 bug,无法生效,参见  以及   。貌似没有办法可以直接实现 IE 地址栏按                UTF-8 编码查询字符串,只好采用如下 workaround:
在大多数浏览器已默认采用 Unicode 的前提下,URL 中的查询参数不乱码的必要条件是中间件里配置 URI 的解码方式也为 UTF-8(比如                Tomcat 中的 URIEncoding)。
通过表单提交发起的请求对于表单中的参数,无论是通过 get 方法(通过 URL 查询参数)还是 post                方法(通过请求体)提交,浏览器(上节提到的三个浏览器均如此)都会根据页面的 ContentType("text/html;                charset=enc")中指定的编码对表单中的数据进行编码,然后发给服务器。在服务器端的程序中我们需要在合适的位置通过                Request.setCharacterEncoding(String enc) 方法设置一致的编码方式,然后才能通过                request.getParameter 获得正确的数据。
表单数据不乱码的前提是页面 content type 中的 charset 和服务器 request 中的 characterEncoding                一致,当然首选都设为"utf-8"。
JavaScriptajaxGet实验发现浏览器对 AjaxGet 请求中 URL 编码的处理与上面讲的对地址栏 URL 的处理略有不同,如表 2 所示:
表 2.                    三种常见浏览器对 ajaxGet 的编码方式浏览器默认                                URI                                编默认查询参数编码 英文 Chrome 54  UTF-8  跟随页面 content type  英文 Firefox 51  UTF-8  UTF-8  英文 IE 11  UTF-8  跟随系统 code page
这里不同浏览器对查询参数的处理差别较大,所以最好使用 encodeURI 或 encodeURIComponent 手动显式地将整个 URL                或者查询字符串按 UTF-8 编码,详细用法如下:
该方法不会对 ASCII 字母和数字及部分标点符号进行编码,比如 - _ . ! ~ * ' ( ) 。 另外该方法的目的是对 URI                进行完整的编码,因此对以下在 URI 中具有特殊含义的 ASCII 标点符号不会进行转换。
;/?&=+$,#
encodeURI() 函数的区别之处在于前者针对的是包含查询字符串的整个 URI,因此未对 URI 中具有特殊含义的 ASCII                标点符号进行转换,而 encodeURIComponent() 函数将转义用于分隔 URI 各个部分的标点符号。
;/?&=+$,#
此外,比较容易与上面四个函数混淆的是 escape/unescape。需要注意的是 escape() 是针对字符串的,而不是针对                URL,其返回的是一个字符的 Unicode 码点的十六进制形式。该方法不会对 ASCII 字母和数字进行编码,也不会对下面这些 ASCII                标点符号进行编码: * @ - _ + . / 。ECMAScript v3 反对使用该方法,推荐使用 decodeURI() 和                decodeURIComponent() 。
总结来说,escape 函数和编码 URL 没关系,编码 URL 用 encodeURI,编码查询参数的时候用                encodeURIComponent(因为查询参数可能是一个需要编码的 url) 其实现在的主流浏览器已经能对 url 默认按 utf-8                编码,中间件那里设置下 URIEncoding 按 utf-8 解码就能解决 url 编码的问题,所以 encodeURI 不太用到。
反倒是由于 IE 对查询参数的编码还是跟随系统,所以最好使用 encodeURIComponent 将其强制转为 ANSI 表示的 utf-8                编码,这样就不用使用浏览器复杂的编码机制了,可以保证跨浏览器使用。
ajaxPost实验发现上文所述的三个浏览器在提交 ajaxPost 请求时对于 URI 和请求体都是默认按 utf-8 编码,而不受 content type                影响。 所以 ajaxPost 不乱码的必要条件是将服务端 request 中的 characterEncoding 设为"utf-8"。




欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) Powered by Discuz! 7.0.0