数据传递转码
数据在传输的过程中,浏览器会对数据进行编码,假如我现在有一条数据 {"name": "测试"}
,如果我们通过 get
方法传递数据,这条数据会被拼接到 url
请求的后面,如:localhost:8080/src/text.html?name=测试
。
uri本身是采用ASCII编码的,所以如果是非 ASCII
编码集的字符在传输时都会被编码,编码方法和 encodeURI
的编码规则相同,但是这里的编码规则是由浏览器控制的,不同的浏览器采用的编码方式 (UTF-8,GBK)
不一样,被编码的数据发送给服务器,服务器用 iso-8859-1
编码对数据解码,后端人员通过 request.getParameter("name")
获取参数数据,且获得的数据都是经过解码过的,而解码过程中程序里无法指定,对于 get
请求获得的数据 request.setCharacterEncoding("字符集")
指定解码规则无效。
如果是 post
方法传递数据,浏览器也会对数据进行编码,如果我们在 ajax
请求头里面设置了 setRequestHeader("ContentType","application/x-www-form-urlencoded;charset=UTF-8")
; 浏览器就会以charset值进行编码,如果没有设置则由网页 meta
标签的 charset
属性决定,被编码过的数据发送给服务器,服务器用 iso-8859-1
编码对数据解码,对于post请求发来的数据后端人员可以使用 request.setCharacterEncoding("字符集")
指定解码规则。
相信你已经找出了乱码的原因,由于 get
方法传的的数据,浏览器的转码规则和服务器的解码规则不一致出现了乱码,我们一般是怎么解决的呢?get
方式发送的数据如果有中文和特殊字符前端会先使用 encodeURI()
方法转码,这样 url
里面的就都是 ASCII
编码集的字符,省去了浏览器的转码,且 encodeURI()
的转码规则可控,受网页 meta
头的 charset
属性影响,
- 标签的
charset
属性为utf-8
时:
var data = '百度&%$#@baidu';
console.log(encodeURI(data));
// %E7%99%BE%E5%BA%A6&%25$#@baidu
console.log(encodeURIComponent(data));
// %E7%99%BE%E5%BA%A6%26%25%24%23%40baidu
- 标签的
charset
属性为GBK
时:
var data = '百度&%$#@baidu';
console.log(encodeURI(data));
// %E9%90%A7%E6%83%A7%E5%AE%B3&%25$#@baidu
console.log(encodeURIComponent(data));
// %E9%90%A7%E6%83%A7%E5%AE%B3%26%25%24%23%40baidu
后端人员获取到用iso-8859-1解码后的数据一般先还原回字节码,然后用前后端协定的方式解码数据,还可以在服务器的配置文件里面进行配置解码规则。而post请求发送的数据可以使用request.setCharacterEncoding("字符集")指定解码规则来达到前后端转码统一。
当我们需要传递的数据量大,结构复杂,业务场景,技术实现需要的时候我们就又会发现,乱码的问题依然存在,比如
- json格式的数据由于特殊字符导致数据解析出现问题,
- xml格式数据由于特殊字符破坏xml格式导致数据解析出现问题,
- 前后端一些语言自带的转码方法对一些特殊字符转码结果不一致,以及并非所有特殊字符都会被转码...
如果我们使用 encodeURI
或者 encodeURIComponent
编码传输到后端,后端解码之后的数据总会因为一些特殊字符的转码不一致导致结果不一样,如果再加上 md5
校验之类的,前端传递的数据就会因为 md5
不同无法解析入库。
那么这个时候我们就该考虑有没有一种转码规则可以解决以上所有的问题呢?base64
转码你值得拥有。
base64转码
base64
编码是从二进制到字符的过程,编码受 html
页面头部 mate
;标签的 charset
属性影响,charset
属性不同,编码转为二进制时,产生的二进制也是不一样的,所以最终产生的 base64
字符也不一样。
mate
标签的charset
属性为utf-8
时:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>base64</title>
</head>
<body>
<script src="base64.min.js"></script>
<script>
var data = '百度&%$#@baidu';
console.log(base64encode(data));
// fqYmJSQjQGJhaWR1
</script>
</body>
mate
标签的charset
属性为GBK
时:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="GBK">
<title>base64</title>
</head>
<body>
<script src="base64.min.js"></script>
<script>
var data = '百度&%$#@baidu';
console.log(base64encode(data));
// J+ezJiUkI0BiYWlkdQ==
</script>
</body>
有关 base64
转码原理有兴趣可自行百科。
总结
所以工作中如果涉及到文本框输入等复杂的内容数据传递为了避免中文乱码以及各种特殊符号带来的困扰就使用 base64
转码传递。 如果只是URL里面的传递简单的参数可以使用 encodeURI
和 encodeURIComponent
等转码。