url中帶有加號的處理方法

最近項目中出現了一個問題,圖片的路徑正確,可是轉成URL以後沒法找到。。。html

找了各類緣由以後,最後注意到URL中的圖片名稱和本地路徑名稱有點不同,以下圖ajax

1.URL圖片數據庫

2.本地路徑編程

 

上網查了一下發現加號轉URL應該是轉成「%2B」 ,而「%20」表明的是空格,再回頭找到數據庫,果真發現「+」都被替換成「 」了,如圖跨域

3.數據庫路徑瀏覽器

對應的URL路徑中「%20」改回「+」對應編碼「%2B」以後,也終於能夠正常查看圖片了,安全

4.URL路徑將「%20」改回「+」cookie

 

 

 

 

如下是網上找到的一片大神的文章,在此摘錄,以防遺失:app

連接:http://www.verydemo.com/demo_c128_i96717.html編程語言

url中帶有加號的處理方法

 

問題原由: 
客戶訂購了一關鍵字爲"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編解碼的時候千萬別被這些假象給迷惑了。

相關文章
相關標籤/搜索