URL编码中的空格(编码以后变为+)

最近测试MM反映查看Log的时候会在有些请求中看到“+”,但是最后的结果却没有问题。当时感觉很诡异,走读代码定位发现是因为调用了java.net.URLEncoder的方法出现。后来研究发现才发现没这么简单啊。

总结:在HTML4.0.1中,基于RFC-1738标准,‘ ’在URL编码以后为 ‘+’,只有JS中由于基于RFC-2396标准,‘ ’在URL编码以后为‘%20’。

java代码:

代码片段:
    String tempString = "Hello, World!";
    String temStringAfterEncode = "";

    try {
        temStringAfterEncode = java.net.URLEncoder.encode(tempString,"UTF-8");
    } catch (java.io.UnsupportedEncodingException e) {
        Log.i("UrlDemo", "bad encoding type"); 
    }

    Log.i("UrlDemo", tempString); 
    Log.i("UrlDemo", temStringAfterEncode); 

    android.net.Uri.encode(tempString);
    Log.i("UrlDemo", tempString); 
    Log.i("UrlDemo", temStringAfterEncode); 


结果如下:

    07-21 11:47:28.695: I/UrlDemo(1222): Hello, World!
    07-21 11:47:28.695: I/UrlDemo(1222): Hello%2C+World%21
    07-21 11:47:28.705: I/UrlDemo(1222): Hello, World!
    07-21 11:47:28.705: I/UrlDemo(1222): Hello%2C+World%21

走读代码发现java将’ ‘转成了’+’。由于之前做过比较久web前端,映像中URL编码规则应该是将空格转为%20。上网看了下,又貌似都是对的,决定试一试。先用站长工具测试了一下URL Encode(如下图),瞬间晕倒,竟然‘+’才是主流的。

地址: http://tool.chinaz.com/Tools/URLEncode.aspx 编码结果:

仍不死心,继续用php测试一番。

PHP代码

代码片段:     
     $tempString = "Hello, World!";
     $temStringAfterEncode = urlencode($tempString);
     echo $tempString ."\n".$temStringAfterEncode."\n";
执行结果:
    $ /usr/bin/php ./urlDemo.php 
    Hello, World!
    Hello%2C+World%21

·

再次崩溃,是谁伤害了我?

最后用JS试一下:

好吧,原来是JS坑了我,罪魁祸首是JS,这到底是为什么呢?

怒而翻身回去google一把,在W3C找到HTML标准,根据HTML4.01标准

‘ ’确实是被 ‘+’替代,他使用的编码标准为RFC-1738。

而JS使用的将‘ ’ 转义为%20的编码标准为RFC-2396标准。

Encodes characters in the given string as'%'-escaped octets using the UTF-8 scheme. Leaves letters ("A-Z","a-z"), numbers ("0-9"), and unreserved characters("_-!.~'()*") intact. Encodes all other characters.

总结:

###在HTML4.0.1中,基于RFC-1738标准,‘ ’在URL编码以后为 ‘+’,只有JS中由于基于RFC-2396标准,‘ ’在URL编码以后为‘%20’。

最后推荐一个MSDK开发使用的encode函数:

/**
 * URL encode推荐方法
 * @param value
 * @return
 */
public static String encode(String value) {
	String encoded = "";
	try {
		encoded = URLEncoder.encode(value, "UTF-8");
	} catch (UnsupportedEncodingException ignore) {
	}
	StringBuffer buf = new StringBuffer(encoded.length());
	char focus;
	for (int i = 0; i < encoded.length(); i++) {
		focus = encoded.charAt(i);
		if (focus == '*') {
			buf.append("%2A");
		} else if (focus == '+') {
			buf.append("%20");
		} else if (focus == '%' && (i + 1) < encoded.length()
				&& encoded.charAt(i + 1) == '7'
				&& encoded.charAt(i + 2) == 'E') {
			buf.append('~');
			i += 2;
		} else {
			buf.append(focus);
		}
	}
	return buf.toString();
	
}

上述代码地址:https://github.com/bihe0832/MyDemo/tree/master/Common

博客中代码地址:https://github.com/bihe0832/MyDemo/tree/master/UrlDemo

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏俞其荣的博客

Android Architecture Component之LiveData解析HeaderLiveDataFooter

Android Architecture Component 是 Google 在 2017 年推出的一套帮助开发者解决 Android 架构设计的方案。里面有...

13930
来自专栏Java学习之路

JavaTCP和UDP套接字编程

原文地址:http://www.cnblogs.com/MindMrWang/p/8919890.html 在我们刚开始入门Java后端的时候可能你会觉得有点...

12020
来自专栏IT开发技术与工作效率

VBA下载

20940
来自专栏Laoqi's Linux运维专列

利用iptables防止syn flood攻击

51340
来自专栏码匠的流水账

ConcurrentLinkedQueue使用实例

ConcurrentLinkedQueue是一个基于链接节点的无界线程安全队列,它采用先进先出的规则对节点进行排序,当我们添加一个元素的时候,它会添加到队列的尾...

24530
来自专栏菩提树下的杨过

jQuery扩展以及gzip压缩测试

<!doctype html> <html> <head> <meta http-equiv="content-type" content="text/h...

29750
来自专栏JetpropelledSnake

SNMP学习笔记之SNMP报文协议详解

简单网络管理协议(SNMP)是TCP/IP协议簇的一个应用层协议。在1988年被制定,并被Internet体系结构委员会(IAB)采纳作为一个短期的网络管理解决...

16420
来自专栏james大数据架构

AsyncTask和Handler对比

1 ) AsyncTask实现的原理,和适用的优缺点 AsyncTask,是android提供的轻量级的异步类,可以直接继承AsyncTask,在类中实现异步操...

22950
来自专栏恰童鞋骚年

ASP.Net MVC开发基础学习笔记:二、HtmlHelper与扩展方法

  在ASP.Net MVC中微软并没有提供类似服务器端控件那种开发方式,毕竟微软的MVC就是传统的请求处理响应的回归。所以抛弃之前的那种事件响应的模型,抛弃服...

13920
来自专栏Android 研究

Android Handler机制3之SystemClock类

官网位置在https://developer.android.com/reference/android/os/SystemClock.html

20220

扫码关注云+社区

领取腾讯云代金券