前端开发涉及到的编码问题

前言

URL只能使用英文字母、阿拉伯数字和某些标点符号,不能使用其他文字和符号。比如,世界上有英文字母的网址"http://www.abc.com",但是没有希腊字母的网址"http://www.aβγ.com"(读作阿尔法-贝塔-伽玛.com)。这是因为网络标准RFC 1738做了硬性规定:

"...Only alphanumerics [0-9a-zA-Z], the special characters "$-_.+!*‘()," [not including the quotes - ed], and reserved characters used for their reserved purposes may be used unencoded within a URL."

"只有字母和数字[0-9a-zA-Z]、一些特殊符号"$-_.+!*‘(),"[不包括双引号]、以及某些保留字,才可以不经过编码直接用于URL。"

这意味着,如果URL中有汉字,就必须编码后使用。但是麻烦的是,RFC 1738没有规定具体的编码方法,而是交给应用程序(浏览器)自己决定。这导致"URL编码"成为了一个混乱的领域。

如下:

1:地址栏输入和点击url访问浏览器时,chrome下无论请求地址和参数,均经过utf-8编码;非chrome浏览器,其中请求地址用utf-8编码,参数按操作系统编码进行编码(ie下的编码参数部分都不带%)。但参数中含特殊符号时,未确定何特殊符号会被编码。

例子:http://www.google.com/小明|=?param=小明|=
a.上面的url在中文xp的chrome下,发送的请求地址是

http://www.google.com/%E5%B0%8F%E6%98%8E%7C=?param=%E5%B0%8F%E6%98%8E|=

b.在中文xp的firefox下,发送的请求地址是
http://www.google.com/%E5%B0%8F%E6%98%8E%7C=?param=%D0%A1%C3%F7|= 

c.在中文xp的ie下,发送的请求地址是
http://www.google.com/%E5%B0%8F%E6%98%8E%7C=?param=С??|=

2:超链接中的请求,请求地址用utf-8编码,参数用页面编码,但是在ie下的参数不带%号。

在上面的例子中,在页面指定utf-8编码下,参数部分会变成:param=%E5%B0%8F%E6%98%8E|=。但ie会变成param=E5B08FE6988E|=。

3:js进行超链接访问时,和超链接情况一致。

4:ajax异步请求时,ie总是用gbk来编码,包括网页路径和参数,非ie和超链接请求一致。

在上面例子中,ie下发送的请求会变成:http://www.google.com/%D0%A1%C3%F7%7C=?param=d0a1c3f7|=

form提交涉及到的编码

form 表单中有一个 accept-charset  属性,如果没有此属性会用页面编码来提交,如果页面编码没有就是 utf-8编码。

两个应用编码不同,一个是GBK编码,另一个是UTF-8编码。现在要在GBK编码的应用里使用表单向UTF-8编码的应用里提交数据,很显然,如果不做特殊处理的话,会出现乱码。 

解决方案:
在GBK编码的页面里编写如下代码:
<form method="post" action="..." accept-charset="utf-8"> ... </form> 

如此的代码在Firefox等正常的浏览器下没有任何问题,但是遇到IE这个变态浏览器就不灵光了,我们还得用点不入流的手段Hack一下:
<form method="post" action="..." accept-charset="utf-8" onsubmit="document.charset=‘utf-8‘;"> ... </form> 

ajax 中涉及到的编码

ajax 提交到服务器的编码上面已经讨论过。但是获取后台内容也会有乱码的情况出现:

如果ajax 后台返回的不是utf-8的编码的二进制流,那么在xmlhttprequest 对象的responseText 方法中字符就会乱码,因为浏览器默认用utf-8来解码。

我在后台返回时的conent-type 中也明确书写了charset :gbk 。但是实测没起到作用。 这个等有时间在验证

注意:

无论何种方式提交的服务器,浏览器都会转化成ascll字符,然后以ascll对应的码点转成二进制进行传输。对于那么不能直接转成ascll字符的,比如汉字。也会先用以上的编码方式转成ascll字符。
比如:
春节 ==》%E6%98%A5%E8%8A%82  utf-8编码
       ==》 %B4%BA%BD%DA            gbk 编码

在utf-8编码下,一个汉字 会有9个字节进行传输。

在一个html标签的属性中会有长度的限制。比如
a 标签的href 的长度限制,计算这个长度时要注意以上的细节

由于各个浏览器处理起来的不一致,所以我们需要用js来处理编码,因为js的处理结果都是一致的,都是utf-8编码。三个函数:

1.escape()

虽然这个函数现在已经不提倡使用了,但是由于历史原因,很多地方还在使用它,所以有必要先从它讲起。

实际上,escape()不能直接用于URL编码,它的真正作用是返回一个字符的Unicode编码值。比如"春节"的返回结果是%u6625%u8282,也就是说在Unicode字符集中,"春"是第6625个(十六进制)字符,"节"是第8282个(十六进制)字符。

它的具体规则是,除了ASCII字母、数字、标点符号"@ * _ + - . /"以外,对其他所有字符进行编码。在\u0000到\u00ff之间的符号被转成%xx的形式,其余符号被转成%uxxxx的形式。对应的解码函数是unescape()。

 escape对0-255以外的unicode值进行编码时输出%u****格式,其它情况下escape,encodeURI,encodeURIComponent编码结果相同。

所以,"Hello World"的escape()编码就是"Hello%20World"。因为空格的Unicode值是20(十六进制)

首先,无论网页的原始编码是什么,一旦被Javascript编码,就都变为unicode字符。也就是说,Javascipt函数的输入和输出,默认都是Unicode字符。这一点对下面两个函数也适用。

其次,escape()不对"+"编码。但是我们知道,网页在提交表单的时候,如果有空格,则会被转化为+字符。服务器处理数据的时候,会把+号处理成空格。所以,使用的时候要小心。可以这样处理下 str.replace(/+/g,"%u002B");

escape不编码字符有69个:*,+,-,.,/,@,_,0-9,a-z,A-Z

2.encodeURI()

encodeURI()是Javascript中真正用来对URL编码的函数。
它着眼于对整个URL进行编码,因此除了常见的符号以外,对其他一些在网址中有特殊含义的符号"; / ? : @ & = + $ , #",也不进行编码。编码后,它输出符号的utf-8形式,并且在每个字节前加上%。它对应的解码函数是decodeURI()。 需要注意的是,它不对单引号‘编码。

3.encodeURIComponent()

最后一个Javascript编码函数是encodeURIComponent()。与encodeURI()的区别是,它用于对URL的组成部分进行个别编码,而不用于对整个URL进行编码。
因此,"; / ? : @ & = + $ , #",这些在encodeURI()中不被编码的符号,在encodeURIComponent()中统统会被编码。至于具体的编码方法,两者是一样。它对应的解码函数是decodeURIComponent()。encodeURIComponent不编码字符有71个:!, ‘,(,),*,-,.,_,~,0-9,a-z,A-Z

上面说到form post提交的时候可以设置 charset。那ajax提交的时候怎么办?比如怎么把上面三个函数处理过的utf-8编码的字符发送到GBK编码的后台

首先,当我们使用提交时,浏览器会根据当前页面编码,encode一次,然后发送到服务端,服务端接收到表单,会自动dencode一次,通常这个过程是对程序是透明的。即,浏览器把请求翻译成ascll字符传输,服务端接受二进制并翻译成ascll进行dencode。

这个dencode 和前端的encode 的编码不一致问题就来了。

解决:

1.使用escape函数 把中文换成%uxxxx的形式提交。这样浏览器encode的时候不会在处理了。到了后台,dencode完也是这种形式。 之后再用utf-8转一下。

2.

1.在A应用处用encodeURIComponent()2次编码参数数据,如k=中文(utf-8编码为%E4%B8%AD%E6%96%87),进行2次编码后,encodeURIComponent(encodeURIComponent(k))=%25E4%25B8%25AD%25E6%2596%2587

2.将请求发送到url2 = http://www.xxx.com/a.htm?k=%25E4%25B8%25AD%25E6%2596%2587&encoding=utf-8

3.url2对应应用收到这个请求后,web容器会对%25进行解码,变成%,对应request.getParameter("k")=%E4%B8%AD%E6%96%87

4.再URLDecoder.decode("%E4%B8%AD%E6%96%87", "UTF-8")就能解码回原来的中文而不会乱码了。

从编码到页面呈现中涉及的编码

我们在开发过程中新建文件(js,css,html),都会有默认的编码方式存储在硬盘上。不过的开发工具新建文件时的编码方式不同。

源代码发布到web容器后,用户在浏览器访问我们的文件,web容器以二进制流发送我们的文件给浏览器。

浏览器要解析这个二进制流。那么问题来了,浏览器用什么编码去解析?

1.根据http协议中的 content-type 中的charset ,content-type中的charset的优先级最高,如果有charset选项浏览器将忽略以下规则

2.html页面中meta标签中的charset。(js,css 也有charset ,如果有将用此charset ,如果没有就用宿主html的charset)

3.浏览器默认charset

浏览器解析完这个二进制流之后,会把这些信息存在变量中。 变量在内存中存储的编码方式就是浏览器默认的了,跟以上的规则都没有关系了。 包括在html input 中输入字符都是浏览器以默认编码存储在内存中。

时间: 2024-10-31 16:20:55

前端开发涉及到的编码问题的相关文章

前端开发规范之html编码规范

原则1.规范 .保证您的代码规范,趋html5,远xhtml,保证结构表现行为相互分离.2.简洁.保证代码的最简化,避免多余的空格.空行,保持代码的语义化,尽量使用具有语义的元素,避免使用样式属性和行为属性.任何时候都要用尽量简单.尽量少的元素解决问题.3.实用.遵循标准,但是不能以牺牲实用性为代价.4.忠诚.选择一套规范,然后始终遵循.不管代码由多少人参与,都应该看起来像一个人写的一样. 语法1.小写.html标签.html属性全部小写.2.嵌套.所有元素必须正确嵌套.3.闭合.双标签必须闭合

前端开发规范之jQuery编码规范

加载jQuery 在您的页面中优先使用CDN的方式,CDN方式的优点在这里,这里有比较流行的jQueryCDN列表清单(由于国内goolge限制问题,建议使用国内的CDN,例如百度的CDN). [html] view plaincopyprint? <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></scr

前端开发学习笔记(一)深入浅出Javascript

从事开发工作已经有十几年时间了,但一直没有真正涉猎WEB开发,这在当今IT业界听起来有些不可思议哈.从今天开始静下心来,全面深入的学习WEB开发的有关知识.将学习的体会和要点记录下来,以作备忘. 深入浅出Javascript一共12章,按照章节记录. 第一章 前端开发涉及到三个层面:HTML(内容) + CSS(外观) + Javascript(交互/行动) JS脚本不论在<script>块中 还是 嵌入HTML中,都应以";"分号作为结束符.这是一个规范的写法 中文网页应

Web 前端开发环境

创建 Web 前端开发环境 Web 前端开发涉及多种工具,这里将常用工具的安装和配置进行说明,提供了详细的说明,为后继的开发创建一个坚实的基础. 本文介绍的工具有:NodeJS, NPM, Bower, Git 和 Grunt. 1. 安装 NodeJS 和 NPM 一切从 NodeJS 开始吧,官方网址:https://nodejs.org/ NodeJS 既可以为我们提供一个服务器端的 Web 环境,又可以提供一个命令行的工具,既然做 Web 前端开发,那就是我们必然选择的工具了. 为了解决

2015年3月-前端开发月刊

1. 创业 2. 职业|项目管理 3. git 4. 知乎(zhihu) 5. 其它 6. Angular 7. 看书学习 8. 移动开发 9. Html5 10. CSS3 11. Javascript 前言: 技术只是一种手段,不是目的.人生的投资有很多种,很多个方向.技术只是其中的一个方向,是目前兴趣的所在点.兴趣会随着岁月的流逝,年龄的增长,会发生变化. 当然鸡蛋不能放在一个篮子里边,所以, 有空的时候提前看看,创业类的,产品,市场,营销类的书籍,提前给自己找点出路,免得后期技术路线走不

创建 Web 前端开发环境

Web 前端开发涉及多种工具,这里将常用工具的安装和配置进行说明,提供了详细的说明,为后继的开发创建一个坚实的基础. 本文介绍的工具有:NodeJS, NPM, Bower, Git 和 Grunt. 1. 安装 NodeJS 和 NPM 一切从 NodeJS 开始吧,官方网址:https://nodejs.org/ NodeJS 既可以为我们提供一个服务器端的 Web 环境,又可以提供一个命令行的工具,既然做 Web 前端开发,那就是我们必然选择的工具了. 为了解决包管理的问题,NodeJS

【学习笔记】前端开发调试工具与PS切图技巧

[学习过程遇到疑问和延伸阅读] 1.Sublime Text 安装插件的方式 一开始以为直接安装.原来在安装丰富的插件之前,Sublime Text需要通过Package Control这个插件来管理.作为基础插件来管理其他的插件.安装成功之后在菜单栏Preferences下才会有Package Control. "Sublime Text 2 也拥有良好的扩展功能,这就是安装包(Package):通过 Sublime Package Control,安装.升级和卸载 Package 也变得轻松

Web前端开发推荐阅读书籍、学习课程下载

转自http://www.xuanfengge.com/fe-books.html 前言 学校里没有前端的课程,那如何学习JavaScript,又如何使自己成为一个合格的前端工程师呢? 除了在项目中学习和跟着有经验的同事学习,读书也是必不可少的.书中有着相对完整的知识体系,每读一本好书都会带来一次全面的提高. 而如果深一脚浅一脚的学习,写出代码的质量会参差不齐.初学者的首要任务是成为靠谱的熟练开发者,能够稳定的输出有一定质量的代码. 前端技术发展速度特别快,总是涌现出很多新的东西,需要不断的学习

Web前端开发十日谈

一直想写这篇“十日谈”,聊聊我对Web前端开发的体会,顺便解答下周围不少人的困惑和迷惘.我不打算聊太多技术,我想,通过技术的历练,得到的反思应当更重要. 我一直认为自己是“初级”前端开发工程师,一方面我入道尚浅,只有短短几年,另一方面我自知对技术的钻研并不深入,可能是由于环境的原因,当然最重要的是,我幸运的参与到互联网崛起的浪潮之巅.时势造就了一批技能薄弱但备受追捧的“弄潮者”,这在很大程度上影响我们对“技术本质”的洞察力,多年来也一直未有成体系的“前端技术”布道佳作,以至于当下多数人对前端技术