浏览器url传的中文是啥编码格式

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浏览器url传的中文是啥编码格式相关的知识,希望对你有一定的参考价值。

参考技术A ISO-8859-1 参考技术B 在项目中碰到了ajax传来的参数,后台接收值乱码(如下图)的问题 在此记录一下
前台:

后台:

解决问题
为什么需要编码
怎样编码
实际出现的问题解决方法
1.为什么需要编码?
URL 只能使用 ASCII 字符集来通过因特网进行发送。
也就是说URL只能使用英文字母、阿拉伯数字和某些标点符号,不能使用其他文字和符号

这意味着 如果URL中有汉字,就必须编码后使用。
但是麻烦的是 标准的国际组织并没有规定具体的编码方法,而是交给应用程序(浏览器)自己决定。
这导致"URL编码"成为了一个混乱的领域。
1.1 浏览器对于中文的编码
Chrome浏览器和火狐的浏览器是一样的如下图,"文"和"章"的utf-8编码分别是"E6 96 87"和"E7 AB A0" ,
下图所示的"%e6%96%87%e7%ab%a0"就是按照顺序,在每个字节前加上%而得到的

Edge浏览器和IE浏览器是一样的,如下图 这个的编码方式我没看出来,希望高手指点

1.2 需要编码的原因还有几点:
你有没有想过,Ukey=value这种传参方式式中, Value中包含 ? 或者 = 怎么办呢
你有没有想过,不同的操作系统、浏览器、不同的网页字符集(charset)会对你的传值造成影响呢
如果你都考虑过,毫无疑问你早就知道需要编码的原因了
2.怎样编码?
Url编码通常也被称为百分号编码(percent-encoding),是因为它的编码方式非常简单,
使用%百分号加上两位的字符——0123456789ABCDEF——代表一个字节的十六进制形式
对于ASCII字符,字母a 在ASCII码中对应的字节是0x61,那么Url编码之后得到的就是%61,
字母abc, url编码后得到的就是%61%62%63
对于非ASCII字符,RFC文档建议使用utf-8对其进行编码得到相应的字节,然后对每个字节执行百分号编码。
如"中文"使用UTF-8字符集得到的字节为0xE4 0xB8 0xAD 0xE6 0x96 0x87,经过Url编码之后得到"%E4%B8%AD%E6%96%87"。
使用javascript先对URL编码,然后再向服务器提交,不要给浏览器插手的机会
这样就能保证客户端只用一种编码方法向服务器发出请求

3.实际出现的问题解决方法
首先说一下js的三种编码函数,escape、encodeURI和encodeURIComponent
3.1.escape函数:
js中编码出生最早的一个,不提倡使用,原因是它不符合我上边(【怎样】)说的url编码原则
真正作用是:
返回一个字符的Unicode编码值,为的是方便他们能在所有计算机上可读
具体规则是:
所有空格、标点以及其他非ASCII字符都用%xx编码替换; 例如空格返回的是%20 字符值大于255的字符以%uxxxx格式储存
所以以后如果看到%u的编码,那就是escape函数
看下边这个列子 你就很清楚的知道它的具体转换规则了

项目中使用:
前台:
function HandlerAddress() $.ajax( type: "get", //用的是js的escape方法 url: "handler/Handler.ashx?address=" + escape("朝阳区大屯路东"), contentType: "application/json; charset=utf-8", success: function (data) //todo成功方法 , error: function (XMLhttpRequest, textStatus, errorThrown) //todo失败方法 )

后台:

QueryString 这个函数会自动解码,所以不需要写什么解码的语句。
还有一点需要注意的是:
escape()不对"+"编码。但是我们知道,网页在提交表单的时候,如果有空格,则会被转化为+字符。服务器处理数据的时候,会把+号处理成空格。所以,使用的时候要小心。
3.2.encodeURI函数
这个函数才是javascript中真正用来对URL编码的函数
规则就是我上面第二部分所说的,采用utf-8编码。
前台:

后台:

用这个方法会存在乱码的问题,看到很多人问这问题的时候,回答者都是让采用escape这种方法,难道这样问题就解决了吗?
如果我想用 Jquery的serialize()方法 来获取表单值并且序列化(标准URL编码)传到后台就不方便用escape啦
解决乱码问题:
出现乱码的原因是我的web config文件里有这样的配置:
<globalization requestEncoding="gb2312" responseEncoding="gb2312" />

解决方案1:去掉这个设置或者改成utf-8的(这个方案的利害不用说,尤其是在项目已经快完成的时候)
解决方案2:利用ajax的post方法,或者用Get方法,但必须作为方法的Data参数,这样在后台接收到的数据不会被编码
前台:
$.ajax( type: "get", //用的是js的encodeURI方法 url: "handler/Handler.ashx", //作为Data参数 data: address: encodeURI("朝阳区大屯路东") , contentType: "application/json; charset=utf-8", success: function (data) //todo成功方法 , error: function (XMLhttpRequest, textStatus, errorThrown) //todo失败方法
)

后台:需要手动解码一次
string ad =HttpUtility.UrlDecode(context.Request["address"]);

HttpUtility.UrlDecode和Server.UrlDecode不同的是,HttpUtility.UrlDecode是有重载的,可以指定编码的方式
例如:
string adsx = HttpUtility.UrlDecode(context.Request.QueryString["address"],System.Text.Encoding.UTF8);

解决方案3:获取已编码的原始数据,自己进行解码
通过观察Request的对象,可以发现context.Request.Url.Query是未解码的数据,这就太棒了

代码:
string address= HttpUtility.ParseQueryString(context.Request.Url.Query, Encoding.UTF8)["address"];

解决方案4(探讨):先将QueryString解码的数据按照他原来的方式进行编码,然后再用utf8进行解码,这个方法有点问题,最后一个字符会出现乱码,还没找到原因..

在将数据编码的时候,就不是原来的浏览器发送的编码值了,正确的是最后边应该是%9C,但现在却是%3f
3.3.encodeURIComponent函数
与encodeURI()的区别是,它用于对URL的组成部分进行个别编码,而不用于对整个URL进行编码。
因此,"; / ? : @ & = + $ , #",这些在encodeURI()中不被编码的符号,在encodeURIComponent()中统统会被编码
具体的编码规则是和encodeURI函数是一样的,如下,encodeURI不会编码 ? 和 @ ,而encodeURIComponent会

encodeURIComponent这个函数就和他的名字一样,是对URI中的一个组件进行编码,不能用于全部的URI

URL 编码 Unicode 字符的正确方法是啥?

【中文标题】URL 编码 Unicode 字符的正确方法是啥?【英文标题】:What is the proper way to URL encode Unicode characters?URL 编码 Unicode 字符的正确方法是什么? 【发布时间】:2010-10-29 02:35:44 【问题描述】:

我知道非标准的 %uxxxx 方案,但这似乎不是一个明智的选择,因为该方案已被 W3C 拒绝。

一些有趣的例子:

心脏字符。 如果我在浏览器中输入:

http://www.google.com/search?q=♥

然后复制粘贴,我看到了这个网址

http://www.google.com/search?q=%E2%99%A5

这看起来像是 Firefox(或 Safari)正在这样做。

urllib.quote_plus(x.encode("latin-1"))
'%E2%99%A5'

这是有道理的,除了不能用 Latin-1 编码的东西,比如三点字符。

如果我输入网址

http://www.google.com/search?q=…

到我的浏览器然后复制粘贴,我得到了

http://www.google.com/search?q=%E2%80%A6

返回。这似乎是这样做的结果

urllib.quote_plus(x.encode("utf-8"))

这是有道理的,因为……不能用 Latin-1 编码。

但我不清楚浏览器如何知道是使用 UTF-8 还是 Latin-1 解码。

因为这似乎是模棱两可的:

In [67]: u"…".encode('utf-8').decode('latin-1')
Out[67]: u'\xc3\xa2\xc2\x80\xc2\xa6'

有效,所以我不知道浏览器如何判断是使用 UTF-8 还是 Latin-1 解码。

我需要处理的特殊字符的正确做法是什么?

【问题讨论】:

您的两个示例都编码为 UTF-8。第一个肯定不是 Latin-1,因为它有三个字节长...... %E2%99%A5 是 the "black heart suit" in UTF-8 字节值的十六进制。那颗黑色的心不是Latin-1 character set 的一部分。 要可靠地查看浏览器的编码方式和内容(以及许多其他有用的信息),请使用大多数现代浏览器中内置的开发人员工具,或获取免费的 HTTP 调试器,如 Fiddler。 【参考方案1】:

我总是用 UTF-8 编码。来自Wikipedia page on percent encoding:

通用 URI 语法要求提供 URI 中字符数据表示的新 URI 方案实际上必须表示来自未保留集中的字符而无需翻译,并且应根据 UTF-8 将所有其他字符转换为字节,然后对这些值进行百分比编码。此要求于 2005 年 1 月随RFC 3986 的发布而引入。在此日期之前引入的 URI 方案不受影响。

似乎因为过去还有其他公认的 URL 编码方法,浏览器尝试了几种解码 URI 的方法,但如果你是编码的人,你应该使用 UTF-8。

【讨论】:

UTF-8 也应该使用,因为它是替代旧 URL 标准的新 IRI 标准(RFC 3987,tools.ietf.org/html/rfc3986)允许的唯一编码。 如果其他人和我一样惊讶,@RemyLebeau 的评论中的文本提到了 RFC3987,但链接是旧规范 3896。正确的 URL 显然是 tools.ietf.org/html/rfc3987 是的,很抱歉。 URI 由 RFC 3986 定义,IRI 由 RFC 3987 定义。【参考方案2】:

一般规则似乎是浏览器根据提供表单的页面的内容类型对表单响应进行编码。这是一个猜测,如果服务器向我们发送“text/xml; charset=iso-8859-1”,那么他们期望返回相同格式的响应。

如果您只是在 URL 栏中输入 URL,则浏览器没有可处理的基本页面,因此只能猜测。因此,在这种情况下,它似乎一直在使用 utf-8(因为您的两个输入都产生了三个八位字节形式的值)。

可悲的事实是,AFAIK 对于查询字符串中的值或 URL 中的任何字符应该被解释为什么字符集没有标准。至少在查询字符串中的值的情况下,没有理由假设它们一定确实对应于字符。

这是一个已知问题,您必须告诉服务器框架您希望查询字符串编码为哪个字符集——例如,在 Tomcat 中,您必须调用 request.setEncoding() (或一些类似的方法) 你调用任何 request.getParameter() 方法之前。缺乏关于这个主题的文档可能反映了许多开发人员对这个问题缺乏认识。 (我经常问 Java 的面试者 Reader 和 InputStream 的区别是什么,而且经常会一脸茫然)

【讨论】:

RFC 3987 (tools.ietf.org/html/rfc3986) 定义了一种标准编码 - 编码不允许未编码的字符时必须使用 UTF-8。【参考方案3】:

IRI (RFC 3987) 是取代 URI/URL(RFC 3986 及更早版本)标准的最新标准。 URI/URL 本身并不支持 Unicode(好吧,RFC 3986 添加了未来基于 URI/URL 的协议的规定以支持它,但不更新过去的 RFC)。 "%uXXXX" 方案是在某些情况下允许 Unicode 的非标准扩展,但并非所有人都普遍实施。另一方面,IRI 完全支持 Unicode,并且要求文本在进行百分比编码之前编码为 UTF-8。

【讨论】:

我希望看到对协议的更新,以便在 URL 中完全支持 unicode,而不仅仅是通过百分比编码。 IRI 允许未编码的 Unicode 字符,但保留字符必须编码的少数情况除外。【参考方案4】:

IRI 不会替换 URI,因为在某些情况下(包括 HTTP)只允许使用 URI(实际上是 ASCII)。

相反,您指定一个 IRI,它会在上网时转换为一个 URI。

【讨论】:

【参考方案5】:

第一个问题是您的需求是什么? UTF-8 编码是使用廉价编辑器创建的文本和支持多种语言之间的一个很好的折衷。关于识别编码的浏览器,响应(来自网络服务器)应该告诉浏览器编码。大多数浏览器仍然会尝试猜测,因为在很多情况下,这要么是缺失的,要么是错误的。他们通过读取一些结果流来猜测是否存在不适合默认编码的字符。目前所有浏览器(?我没有检查这个,但它非常接近真实)使用 utf-8 作为默认值。

所以请使用 utf-8,除非您有令人信服的理由使用许多其他编码方案之一。

【讨论】:

以上是关于浏览器url传的中文是啥编码格式的主要内容,如果未能解决你的问题,请参考以下文章

请问这种是啥编码?用PHP如何实现!?

浏览器端将语音转换为URL格式的字符串(base64 位编码)

java中Char到底是啥格式的编码

urlencode浏览器地址编码格式

python是啥编码格式

谁能告诉我附加屏幕截图的编码格式是啥? [关闭]