最近项目中出现了一个问题,图片的路径正确,但是转成URL之后无法找到。。。

找了各种原因之后,最后注意到URL中的图片名称和本地路径名称有点不一样,如下图

1.URL图片

2.本地路径

上网查了一下发现加号转URL应该是转成“%2B” ,而“%20”代表的是空格,再回头找到数据库,果然发现“+”都被替换成“ ”了,如图

3.数据库路径

对应的URL路径中“%20”改回“+”对应编码“%2B”之后,也终于可以正常查看图片了,

4.URL路径将“%20”改回“+”

以下是网上找到的一片大神的文章,在此摘录,以防遗失:

链接:http://www.verydemo.com/demo_c128_i96717.html

url中带有加号的处理方法

分类: 编程语言C语言文章

问题起因: 
客户订购了一关键字为"e+h变送器" , 在首页推荐广告中,会根据用户在search搜索过的关键字进行一个匹配投放。技术实现是UED通过JS获取cookie中的h_keys内容,拼装到 http://xxxxx/advert/ctp_advert.htm?num=4&keyword={keyword}。 这里取出来对应的cookie信息为中文,最后通过一个ajax发起一个GET请求。

所以针对最后的请求是:http://xxxxxx/advert/ctp_advert.htm?num=4&keyword=e+h变送器。 而在服务端接受到对应的请求参数时,发现参数为:e h变送器, +号没了。 初步怀疑跟URL规范相关,需要进行url encode。


问题分析:

查了下JS encode的相关内容, 总于发现+号的秘密。
html中因为一些非标准的做法,将+等同于空格进行处理(当Html的表单被提交时, 每个表单域都会被Url编码之后才在被发送。由于历史的原因,表单使用的Url编码实现并不符合最新的标准。例如对于空格使用 的编码并不是%20,而是+号,如果表单使用的是Post方法提交的,我们可以在HTTP头中看到有一个Content-Type的header,值为 application/x-www-form-urlencoded,大部分应用程序均能处理这种非标准实现的Url编码)。
在搜索引擎中做了下尝试: 
keyword = e h变送器 , url =http: //www.google.cn/search?hl=zh-CN&newwindow=1&q=e+h变送器(空格被转化为+号)
keyword = e+ h变送器 , url = http: //www.google.cn/search?hl=zh-CN&newwindow=1&q=e%2Bh变送器 (+号被进行了转义为%2B,程序才能正常处理)


问题解决:

思路1:
1. 要想正常传输+号而不被转义为空格,需要进行进行编码为%2B。查了下几个编码函数,发现只有encodeURIComponent 才会对+号进行编码处理
2. encodeURIComponent默认为采用UTF-8字符集,理论上只需要在原先的请求中添加_input_charset=utf-8(由 pipeline中的SetLocaleValve进行解析),就可以得到正确的 e+h变送器。

在实施过程中,发现结果并不是预期的那样。 客户端通过js encode后,在服务端解析后一直是乱码。 查了下byte,发现服务端一直是用GBK在进行解析, 针对变送器的UTF-8编码的byte为{-27,-113,-104,-23,-128,-127},客户端用GBK解析后变为{-27.-113.- 104.-23,-63,-63},针对最后两byte因为字符不可见,导致全部被替换为-63。网上查了下,针对 utf-8 -> gbk -> utf-8 在一定情况下就会出现该问题(http://lingqi1818.iteye.com/blog/348953)。


思路2: 
继续追查对应的_input_charset=utf-8未生效的原因,DEBUG看到在SetLocaleValve中的确设置了request.setCharsetEncoding为utf-8。初步怀疑是否跟jboss server的配置有关,查了下跟URIEncoding 和useBodyEncodingForURI 设置有关。 目前公司所使用的jboss为4.05,对应俄tomact配置中只指定了对应的URIEncoding=GBK。正因为这样,导致设置的_input_charset针对GBK的提交没有效果,还是按照GBK进行解析。

1. 考虑将请求由GET换成POST , 这样就可以使用_input_charset

但在实施过程中,和UED沟通过程,针对POST的会引起一个跨域请求的问题。此方案又只能做罢


思路3 (实践成功):

1. UED进行伪url encode的实现 , 将+号进行%2B的编码。 因为目前JS中没有现成的函数,这里只是通过replace(/\+/g, '%2B') 进行了转化。


总 结

针对+号的处理,针对不同的业务场景需要不同的处理方案,描述下几种场景:
1. 非Ajax 请求
可以直接使用Form表单的 GET ,POST的urlencode协议,自动实现+ => %2B 的转化
2. Ajax 请求
* GET请求 : 很无奈,只能使用方案3,人为进行+号转化。
* POST请求(同一应用,非跨域请 求) : 使用encodeURIComponent + _input_charset=utf-8 指定编码进行处理

ps: 前面提的这几种方案,都是基于+号是正常的业务场景进行考虑。同时我们也可以从业务层面进行一个梳理,+号处理是否有其必要性,能从业务数据入口直接规避 那就最好了。

背景知识:


URIEncoding和useBodyEncodingForURI

对于URL提交的数据和表单中GET方式提交的数据,在接收数据的JSP中设置request.setCharacterEncoding参数是不行的, 因为在Tomcat5.0中,默认情况下使用ISO- 8859-1对URL提交的数据和表单中GET方式提交的数据进行重新编码(解码),而不使用该参数对URL提交的数据和表单中GET方式提交的数据进行 重新编码(解码)。要解决该问题,应该在Tomcat的配置文件的Connector标签中设置useBodyEncodingForURI或者 URIEncoding属性,其中useBodyEncodingForURI参数表示是否用request.setCharacterEncoding 参数对URL提交的数据和表单中GET方式提交的数据进行重新编码,在默认情 况下,该参数为false(Tomcat4.0中该参数默认为true); URIEncoding参数 指定对所有GET方式请求(包括URL提交的数据和表单中GET方式提交的数据)进行统一的重新编码(解码)的编码。URIEncoding和useBodyEncodingForURI区别是,URIEncoding是对所有GET方式的请求的数据进行统一的重新编码 (解码),而useBodyEncodingForURI则是根据响应该请求的页面的request.setCharacterEncoding参数对数 据进行的重新编码(解码),不同的页面可以有不同的重新编码(解码)的编码。所以对于URL提交的数据和表单中GET方式提交的数据,可以修改 URIEncoding参数为浏览器编码或者修改useBodyEncodingForURI为true,并且在获得数据的JSP页面中 request.setCharacterEncoding参数设置成浏览器编码。


为什么需要Url编码
1. Url中有些字符会引起歧义 , =,&号等
2. Url的编码格式采用的是ASCII码,而不是Unicode,这也就是说你不能在Url中包含任何非ASCII字符,例如中文

哪些字符需要编码
RFC3986文档规定,Url中只允许包含英文字母(a-zA-Z)、数字(0-9)、-_.~4个特殊字符以及所有保留字符。
Url可以划分成若干个组件,协议、主机、路径等。RFC3986中指定了以下字符为保留字符: ! * ' ( ) ; : @ & = + $ , / ? # [ ]

如何对Url中的非法字符进行编码
Url编码通常也被称为百分号编码(Url Encoding,also known as percent-encoding),是因为它的编码方式非常简单,使用%百分号加上两位的字符——0123456789ABCDEF——代表一个字节的 十六进制形式。Url编码默认使用的字符集是US-ASCII。例如a在US-ASCII码中对应的字节是0x61,那么Url编码之后得到的就是%61,我们在地址栏上输入http: //g.cn/search?q=%61%62%63,实际上就等同于在google上搜索abc了。又如@符号在ASCII字符集中对应的字节为0x40,经过Url编码之后得到的是%40。


Javascript中的escape,encodeURI和encodeURIComponent的区别

Javascript中提供了3对函数用来对Url编码以得到合法的Url,它们分别是escape / unescape,encodeURI / decodeURI和encodeURIComponent / decodeURIComponent。解码和编码的过程是可逆的.

兼容性不同
escape函数是从Javascript1.0的时候就存在了,其他两个函数是在Javascript1.5才引入的。但是由于Javascript1.5已经非常普及了,所以实际上使用encodeURI和encodeURIComponent并不会有什么兼容性问题。

对Unicode字符的编码方式不同
这三个函数对于ASCII字符的编码方式相同,均是使用百分号+两位十六进制字符来表示。但是对于Unicode字符,escape的编码方式是% uxxxx,其中的xxxx是用来表示unicode字符的4位十六进制字符。这种方式已经被W3C废弃了。但是在ECMA-262标准中仍然保留着 escape的这种编码语法。encodeURI和encodeURIComponent则使用UTF-8对非ASCII字符进行编码,然后再进行百分号 编码。这是RFC推荐的。因此建议尽可能的使用这两个函数替代escape进行编码。

适用场合不同
encodeURI被用作对一个完整的URI进行编码,而encodeURIComponent被用作对URI的一个组件进行编码。

安全字符不同

可到这里查看具体方法的使用:http://www.w3school.com.cn/js/jsref_encodeURIComponent.asp
escape(69个) */@+-._0-9a-zA-Z 
encodeURI(82个)!#$&'()*+,/:;=?@-._~0-9a-zA-Z 
encodeURIComponent(71个)!'()*-._~0-9a-zA-Z (注意+ 号未在其安全字符里)


其他和Url编码相关的问题
对于包含中文的Url的处理问题,不同浏览器有不同的表现。例如对于IE,如果你勾选了高级设置“总是以UTF-8发送Url”,那么Url中的路径部分 的中文会使用UTF-8进行Url编码之后发送给服务端,而查询参数中的中文部分使用系统默认字符集进行Url编码。为了保证最大互操作性,建议所有放到 Url中的组件全部显式指定某个字符集进行Url编码,而不依赖于浏览器的默认实现。

另外,很多HTTP监视工具或者浏览器地址栏等在显示Url的时候会自动将Url进行一次解码(使用UTF-8字符集),这就是为什么当你在 Firefox中访问Google搜索中文的时候,地址栏显示的Url包含中文的缘故。但实际上发送给服务端的原始Url还是经过编码的。你可以在地址栏 上使用Javascript访问location.href就可以看出来了。在研究Url编解码的时候千万别被这些假象给迷惑了。

url中带有加号的处理方法的更多相关文章

  1. php curl 传输是url中带有空格的处理方法

    在crul中,应该用%20代替空格,否则,空格以后的数据将get不到.

  2. get请求url中带有中文参数出现乱码情况

    在项目中经常会遇到中文传参数,在后台接收到乱码问题.那么在遇到这种情况下我们应该怎么进行处理让我们传到后台接收到的参数不是乱码是我们想要接收的到的,下面就是我的一些认识和理解. get请求url中带有 ...

  3. 使用JavaScript获取URL中的参数(两种方法)

    本文给大家分享两种方法使用js获取url中的参数,其中方法二是使用的正则表达式方法,大家可以根据需要选择比较好的方法,废话不多说了,直接看详细介绍吧. 方法一: //取url参数 var type = ...

  4. URL中带加号的处理

    问题起因:      客户订购了一关键字为"e+h 变送器" , 在首页推荐广告中,会根据用户在search 搜索过的关键字进行一个匹配投放.技术实现是UED 通过JS 获取coo ...

  5. [故障引起的故事]URL中带加号的处理

    问题起因:      客户订购了一关键字为"e+h 变送器" , 在首页推荐广告中,会根据用户在search 搜索过的关键字进行一个匹配投放.技术实现是UED 通过JS 获取coo ...

  6. JS获取URL中参数值的4种方法

    方法一:正则法 function getQueryString(name) { var reg = new RegExp('(^|&)' + name + '=([^&]*)(& ...

  7. apache使用.htaccess文件中RewriteRule重定向后,URL中的加号无法解析

    今天在使用.htaccess做伪静态的时候,发生一件怪事,URL里存在C++时会有问题,在处理C++这个词的时候,无论如何,$_GET都得不到++,只能得到C空格. 一开始我以为是没用urlencod ...

  8. beego小技巧两则:通过命令行自定义端口和环境,url中带有中划线处理

    1,通过命令行自定义端口和环境 先用flag提取参数,如果要环境,就反向注进去, 如果是端口,就打到beego.Run函数里去. 2,在作router里的url解析时,如果URL中含有-中划线,用严格 ...

  9. php form表单提交时,action url中参数无效的解决方法

    表单提交时get方式的一个错误 <form class="form-inline pull-right" method="get" action=&quo ...

随机推荐

  1. RobotFramework自动化1-环境搭建【转载】

    本篇转自博客:上海-悠悠 原文地址:http://www.cnblogs.com/yoyoketang/tag/robotframework/ 前言 Robot Framework是一款python编 ...

  2. 在OpenResty中使用淘宝的concat进行css和js合并,同时支持GZIP静态压缩

    =======================================================================================cd /usr/local ...

  3. 【原创】DataPackage-数据库、表的区域设置和系统不一致导致处理失败

    问题描述: 最近学习Datapackage,创建完之后,部署处理但总是提示某某字段的区域设置和目标字段的区域设置不一致,具体如图: 测试发现其它的数据库表又没有这类的问题发生,甚是苦恼,搜寻了好久,后 ...

  4. Openjudge1388 Lake Counting【DFS/Flood Fill】

    http://blog.csdn.net/c20182030/article/details/52327948 1388:Lake Counting 总时间限制:   1000ms   内存限制:  ...

  5. Gym - 101194F(后缀数组)

    Mr. Panda and Fantastic Beasts 题意 给出若干个字符串,找到一个最短的字典序最小的字符串且仅是第一个字符串的子串. 分析 对于这种多个字符串.重复的子串问题一般都要连接字 ...

  6. POJ 2566:Bound Found(Two pointers)

    [题目链接] http://poj.org/problem?id=2566 [题目大意] 给出一个序列,求一个子段和,使得其绝对值最接近给出值, 输出这个区间的左右端点和区间和. [题解] 因为原序列 ...

  7. [给自己扫盲]Node.js 究竟是什么?

    Node.js 究竟是什么? 一个 “编码就绪” 服务器 Node 是一个服务器端 JavaScript 解释器,它将改变服务器应该如何工作的概念.它的目标是帮助程序员构建高度可伸缩的应用程序,编写能 ...

  8. python gzip压缩

    1 import urllib2 2 from StringIO import StringIO 3 import gzip 4 5 def loadData(url): 6 request = ur ...

  9. Vue表单和组件

    一.表单 v-model 指令在表单控件元素上创建双向数据绑定,v-model 会根据控件类型自动选取正确的方法来更新元素. <input v-model="message" ...

  10. Spark-Streaming之window滑动窗口应用

    Spark-Streaming之window滑动窗口应用,Spark Streaming提供了滑动窗口操作的支持,从而让我们可以对一个滑动窗口内的数据执行计算操作.每次掉落在窗口内的RDD的数据,会被 ...