http://tools.ietf.org/html/rfc3895
--------------------------------------
在php当中也提供了标准的RFC1738的实现
在PHP Manual中有对两个函数的说明:
urlencode:返回字符串,此字符串中除了 - _ . 之外的所有非字母数字字符都将被替换成百分号(%)后跟两位十六进制数,空格则编码为加号(+)。此编码与 WWW 表单 POST 数据的编码方式是一样的,同时与 application/x-www-form-urlencoded 的媒体类型编码方式一样。由于历史原因,此编码在将空格编码为加号(+)方面与 RFC1738 编码(参见 rawurlencode())不同。
rawurlencode:返回字符串,此字符串中除了 - _ . 之外的所有非字母数字字符都将被替换成百分号(%)后跟两位十六进制数。这是在 RFC 1738 中描述的编码,是为了保护原义字符以免其被解释为特殊的 URL 定界符,同时保护 URL 格式以免其被传输媒体(像一些邮件系统)使用字符转换时弄乱。
我自己的理解:
从上面这篇文章中可以看到 很多人都说 java里 的 UrlEncode 把空格编码成+ 是历史的原因。且10年前都是这样说,2005年 java里就是这样了,现在2017年 都12年过去了 难道还是因为历史的原因吗,什么叫做历史的原因。
在调查一个错误的时候,偶然发现HTML页面中的部分Link含有+,将tag反编译了一下,发现是因为调用了Java.NET.URLEncoder的方法
public static String encode(String s, String enc)
从代码中可以很清晰的看到还特别照顾的将' '转成了'+'。由于印象中的URL编码规则应该是将空格转为%20,就google了一把,结果发现很多人都遇到了这个问题,但基本都是语焉不详。
花了1个多小时仔细搜索了一遍,线索如下:
2、在W3C找到HTML标准的说明
http://www.w3.org/TR/REC-html40/interact/forms.html#h-17.13.4
在这里清楚的看到编码方式是根据ContextType的不同而区别对待的,在form的ContextType是[x-www-form-urlencoded]的时候会对form中的键/值对进行编码,空格被转义成+,其他字符按照[RFC1738]标准处理成%HH的形式。
3、回头再看URLEncoder
发现该类的注释中很明确的写明了:
converting a String to the application/x-www-form-urlencoded MIME format
从以上的结果看来%20似乎只是在使用上的一个误解,因为%20可以被解析成空格,所以就理所当然的认为空格应该被转义为%20。
再进一步,对Java/.Net/JavaScript的相关函数进行下测试,结果发现Java(1.5)与.Net(2.0)的情况一致,但JavaScript的函数还是将空格转换成了%20。看来这个问题的误解完全来自于js的错误……
=====================================================================
看了这篇文章后 再去理解空格的问题,你会发现有三个个协议标准:RFC1738、RFC2396、HTML4.01;
打开上文中的两个链接来看下:
官方说这不是一个bug,我猜测可能是名字上的叫法 让人误解,UrlEncode 应该叫 PostUrlEncode;或者叫WWWFormUrlEncode类。
因为http协议中 有post和get提交:
1.如果是get提交 或者是路径的话 如: http://www.bai du.com?wo=he he&ni=abc 就应该遵循RFC1738、RFC2396;就变成:http://www.bai%20du.com?wo=he%20he&ni=abc;
2.如果是post提交:因为post提交的参数依然是被弄成键值对的方式传递的类似GET的QueryString方式,即需要提交的参数应该是: wo=he he&ni=abc;但是由于 html是一种常用语言,它里面有post提价方式,他也有自己的规范,他规定post生成的键值对参数中 参数的值如果有空格应该编码成+号(注意不是%20)见上面链接打开后的下图:
Java官方的URLEncoder.encode 实际上是为了post请求的content-type为x-www-form-urlencoded来设计的。所以没有什么bug可言。
=============================
1.资源路径中含有空格时应该转码为%20,
举例:http://www.baidu.com/he he/index.jsp -----> http://www.baidu.com/he%20he/index.jsp
2.get请求的QueryString里含有空格的话应该转码为%20;
举例:http://www.abc.com?wo=he he ------> http://www.abc.com?wo=he%20he
3.post请求时,content-type = application/x-www-form-urlencoded (一般默认都是这个)时,空格应该转码为+;
举例:向http://www.abc.com/发post请求,参数的值有空格,最终的参数键值对是 wo=he+he;
2017-04-12 续集。。。。。。。。
2017.11.05补充。。。。。。。。。。。。。。
get请求的时候可以用,TNetEncoding.URL.EncodeQuery,
post请求的时候可以用,TNetEncoding.URL.EncodeForm
2019-11-03 补充。。。。。。。。。。。。
procedure TfrmAesForm.Button3Click(Sender: TObject);
begin
空格的问题,根据国际URL标准,GET请求是包含在路径里的,所以与Post请求的标准不同
GET请求参数包含在URL路径里,他们有一个标准 RFC1738,RFC3986; 此标准要求空格转为%20
POST请求参数不包含在URL路径里,他们的参数传输有一个自己的标准 application/x-www-form-urlencoded MIME format; 此标准要求空格转为+
Memo1.Lines.Add(TNetEncoding.URL.EncodeQuery(' '));//%20 GET请求的参数用这个URLEncode
Memo1.Lines.Add(TNetEncoding.URL.EncodeForm(' '));//+ POST请求的参数用这个URLEncode
Memo1.Lines.Add(TNetEncoding.URL.Encode(' '));//+ get提交的时候不要用这个,这个会搞成+
end;