關(guān)于URL編碼

一、問(wèn)題的由來(lái)

URL就是網(wǎng)址逸邦,只要上網(wǎng)恩沛,就一定會(huì)用到。

bg2010021101.jpg

一般來(lái)說(shuō)缕减,URL只能使用英文字母雷客、阿拉伯?dāng)?shù)字和某些標(biāo)點(diǎn)符號(hào),不能使用其他文字和符號(hào)桥狡。比如搅裙,世界上有英文字母的網(wǎng)址"http://www.abc.com",但是沒(méi)有希臘字母的網(wǎng)址"http://www.aβγ.com"(讀作阿爾法-貝塔-伽瑪.com)裹芝。這是因?yàn)榫W(wǎng)絡(luò)標(biāo)準(zhǔn)RFC 1738做了硬性規(guī)定:

"...Only alphanumerics [0-9a-zA-Z], the special characters "$-_.+!*'()," [not including the quotes - ed], and reserved characters used for their reserved purposes may be used unencoded within a URL."

"只有字母和數(shù)字[0-9a-zA-Z]部逮、一些特殊符號(hào)"$-_.+!*'(),"[不包括雙引號(hào)]、以及某些保留字嫂易,才可以不經(jīng)過(guò)編碼直接用于URL兄朋。"

這意味著,如果URL中有漢字怜械,就必須編碼后使用颅和。但是麻煩的是,RFC 1738沒(méi)有規(guī)定具體的編碼方法缕允,而是交給應(yīng)用程序(瀏覽器)自己決定融虽。這導(dǎo)致"URL編碼"成為了一個(gè)混亂的領(lǐng)域。

下面就讓我們看看灼芭,"URL編碼"到底有多混亂。我會(huì)依次分析四種不同的情況般又,在每一種情況中彼绷,瀏覽器的URL編碼方法都不一樣巍佑。把它們的差異解釋清楚之后,我再說(shuō)如何用Javascript找到一個(gè)統(tǒng)一的編碼方法寄悯。

二萤衰、情況1:網(wǎng)址路徑中包含漢字

打開(kāi)IE(我用的是8.0版),輸入網(wǎng)址"http://zh.wikipedia.org/wiki/春節(jié)"猜旬。注意脆栋,"春節(jié)"這兩個(gè)字此時(shí)是網(wǎng)址路徑的一部分。

bg2010021102.jpg

查看HTTP請(qǐng)求的頭信息洒擦,會(huì)發(fā)現(xiàn)IE實(shí)際查詢(xún)的網(wǎng)址是"http://zh.wikipedia.org/wiki/%E6%98%A5%E8%8A%82"椿争。也就是說(shuō),IE自動(dòng)將"春節(jié)"編碼成了"%E6%98%A5%E8%8A%82"熟嫩。

bg2010021103.png

我們知道秦踪,"春"和"節(jié)"的utf-8編碼分別是"E6 98 A5"和"E8 8A 82",因此掸茅,"%E6%98%A5%E8%8A%82"就是按照順序椅邓,在每個(gè)字節(jié)前加上%而得到的。(具體的轉(zhuǎn)碼方法昧狮,請(qǐng)參考我寫(xiě)的《字符編碼筆記》景馁。)

在Firefox中測(cè)試,也得到了同樣的結(jié)果逗鸣。所以合住,結(jié)論1就是,網(wǎng)址路徑的編碼慕购,用的是utf-8編碼聊疲。

三、情況2:查詢(xún)字符串包含漢字

在IE中輸入網(wǎng)址"http://www.baidu.com/s?wd=春節(jié)"沪悲。注意获洲,"春節(jié)"這兩個(gè)字此時(shí)屬于查詢(xún)字符串,不屬于網(wǎng)址路徑殿如,不要與情況1混淆贡珊。

bg2010021104.jpg

查看HTTP請(qǐng)求的頭信息,會(huì)發(fā)現(xiàn)IE將"春節(jié)"轉(zhuǎn)化成了一個(gè)亂碼涉馁。

bg2010021105.png

切換到十六進(jìn)制方式门岔,才能清楚地看到,"春節(jié)"被轉(zhuǎn)成了"B4 BA BD DA"烤送。

bg2010021106.png

我們知道蟆豫,"春"和"節(jié)"的GB2312編碼(我的操作系統(tǒng)"Windows XP"中文版的默認(rèn)編碼)分別是"B4 BA"和"BD DA"康震。因此澎现,IE實(shí)際上就是將查詢(xún)字符串朱躺,以GB2312編碼的格式發(fā)送出去。

Firefox的處理方法,略有不同。它發(fā)送的HTTP Head是"wd=%B4%BA%BD%DA"。也就是說(shuō)纫普,同樣采用GB2312編碼,但是在每個(gè)字節(jié)前加上了%好渠。

bg2010021107.png

所以昨稼,結(jié)論2就是,查詢(xún)字符串的編碼拳锚,用的是操作系統(tǒng)的默認(rèn)編碼假栓。

四、情況3:Get方法生成的URL包含漢字

前面說(shuō)的是直接輸入網(wǎng)址的情況晌畅,但是更常見(jiàn)的情況是但指,在已打開(kāi)的網(wǎng)頁(yè)上,直接用Get或Post方法發(fā)出HTTP請(qǐng)求抗楔。

根據(jù)臺(tái)灣中興大學(xué)呂瑞麟老師的試驗(yàn)棋凳,這時(shí)的編碼方法由網(wǎng)頁(yè)的編碼決定,也就是由HTML源碼中字符集的設(shè)定決定连躏。

<meta http-equiv="Content-Type" content="text/html;charset=xxxx">

如果上面這一行最后的charset是UTF-8剩岳,則URL就以UTF-8編碼;如果是GB2312入热,URL就以GB2312編碼拍棕。

舉例來(lái)說(shuō),百度是GB2312編碼勺良,Google是UTF-8編碼绰播。因此,從它們的搜索框中搜索同一個(gè)詞"春節(jié)"尚困,生成的查詢(xún)字符串是不一樣的蠢箩。

百度生成的是%B4%BA%BD%DA,這是GB2312編碼事甜。

bg2010021109.jpg

Google生成的是%E6%98%A5%E8%8A%82谬泌,這是UTF-8編碼。

bg2010021108.jpg

所以逻谦,結(jié)論3就是掌实,GET和POST方法的編碼,用的是網(wǎng)頁(yè)的編碼邦马。

五贱鼻、情況4:Ajax調(diào)用的URL包含漢字

前面三種情況都是由瀏覽器發(fā)出HTTP請(qǐng)求宴卖,最后一種情況則是由Javascript生成HTTP請(qǐng)求,也就是Ajax調(diào)用忱嘹。還是根據(jù)呂瑞麟老師的文章嘱腥,在這種情況下,IE和Firefox的處理方式完全不一樣拘悦。

舉例來(lái)說(shuō),有這樣兩行代碼:

url = url + "?q=" +document.myform.elements[0].value; // 假定用戶(hù)在表單中提交的值是"春節(jié)"這兩個(gè)字

http_request.open('GET', url, true);

那么橱脸,無(wú)論網(wǎng)頁(yè)使用什么字符集础米,IE傳送給服務(wù)器的總是"q=%B4%BA%BD%DA",而Firefox傳送給服務(wù)器的總是"q=%E6%98%A5%E8%8A%82"添诉。也就是說(shuō)屁桑,在Ajax調(diào)用中,IE總是采用GB2312編碼(操作系統(tǒng)的默認(rèn)編碼)栏赴,而Firefox總是采用utf-8編碼蘑斧。這就是我們的結(jié)論4。

六须眷、Javascript函數(shù):escape()

好了竖瘾,到此為止,四種情況都說(shuō)完了花颗。

假定前面你都看懂了捕传,那么此時(shí)你應(yīng)該會(huì)感到很頭痛。因?yàn)槔┤埃瑢?shí)在太混亂了庸论。不同的操作系統(tǒng)、不同的瀏覽器棒呛、不同的網(wǎng)頁(yè)字符集聂示,將導(dǎo)致完全不同的編碼結(jié)果。如果程序員要把每一種結(jié)果都考慮進(jìn)去簇秒,是不是太恐怖了鱼喉?有沒(méi)有辦法,能夠保證客戶(hù)端只用一種編碼方法向服務(wù)器發(fā)出請(qǐng)求宰睡?

回答是有的蒲凶,就是使用Javascript先對(duì)URL編碼,然后再向服務(wù)器提交拆内,不要給瀏覽器插手的機(jī)會(huì)旋圆。因?yàn)镴avascript的輸出總是一致的,所以就保證了服務(wù)器得到的數(shù)據(jù)是格式統(tǒng)一的麸恍。

Javascript語(yǔ)言用于編碼的函數(shù)灵巧,一共有三個(gè)搀矫,最古老的一個(gè)就是escape()。雖然這個(gè)函數(shù)現(xiàn)在已經(jīng)不提倡使用了刻肄,但是由于歷史原因瓤球,很多地方還在使用它,所以有必要先從它講起敏弃。

實(shí)際上卦羡,escape()不能直接用于URL編碼,它的真正作用是返回一個(gè)字符的Unicode編碼值麦到。比如"春節(jié)"的返回結(jié)果是%u6625%u8282绿饵,也就是說(shuō)在Unicode字符集中,"春"是第6625個(gè)(十六進(jìn)制)字符瓶颠,"節(jié)"是第8282個(gè)(十六進(jìn)制)字符拟赊。

bg2010021110.png

它的具體規(guī)則是,除了ASCII字母粹淋、數(shù)字吸祟、標(biāo)點(diǎn)符號(hào)"@ * _ + - . /"以外,對(duì)其他所有字符進(jìn)行編碼桃移。在\u0000到\u00ff之間的符號(hào)被轉(zhuǎn)成%xx的形式屋匕,其余符號(hào)被轉(zhuǎn)成%uxxxx的形式。對(duì)應(yīng)的解碼函數(shù)是unescape()谴轮。

所以炒瘟,"Hello World"的escape()編碼就是"Hello%20World"。因?yàn)榭崭竦腢nicode值是20(十六進(jìn)制)第步。

bg2010021111.png

還有兩個(gè)地方需要注意疮装。

首先,無(wú)論網(wǎng)頁(yè)的原始編碼是什么粘都,一旦被Javascript編碼廓推,就都變?yōu)閡nicode字符。也就是說(shuō)翩隧,Javascipt函數(shù)的輸入和輸出樊展,默認(rèn)都是Unicode字符。這一點(diǎn)對(duì)下面兩個(gè)函數(shù)也適用堆生。

bg2010021112.png

其次专缠,escape()不對(duì)"+"編碼。但是我們知道淑仆,網(wǎng)頁(yè)在提交表單的時(shí)候涝婉,如果有空格,則會(huì)被轉(zhuǎn)化為+字符蔗怠。服務(wù)器處理數(shù)據(jù)的時(shí)候墩弯,會(huì)把+號(hào)處理成空格吩跋。所以,使用的時(shí)候要小心渔工。

七锌钮、Javascript函數(shù):encodeURI()

encodeURI()是Javascript中真正用來(lái)對(duì)URL編碼的函數(shù)。

它著眼于對(duì)整個(gè)URL進(jìn)行編碼引矩,因此除了常見(jiàn)的符號(hào)以外梁丘,對(duì)其他一些在網(wǎng)址中有特殊含義的符號(hào)"; / ? : @ & = + $ , #",也不進(jìn)行編碼旺韭。編碼后兰吟,它輸出符號(hào)的utf-8形式,并且在每個(gè)字節(jié)前加上%茂翔。

bg2010021113.png

它對(duì)應(yīng)的解碼函數(shù)是decodeURI()。

bg2010021114.png

需要注意的是履腋,它不對(duì)單引號(hào)'編碼珊燎。

八、Javascript函數(shù):encodeURIComponent()

最后一個(gè)Javascript編碼函數(shù)是encodeURIComponent()遵湖。與encodeURI()的區(qū)別是悔政,它用于對(duì)URL的組成部分進(jìn)行個(gè)別編碼,而不用于對(duì)整個(gè)URL進(jìn)行編碼延旧。

因此谋国,"; / ? : @ & = + $ , #",這些在encodeURI()中不被編碼的符號(hào)迁沫,在encodeURIComponent()中統(tǒng)統(tǒng)會(huì)被編碼芦瘾。至于具體的編碼方法,兩者是一樣集畅。

bg2010021115.png

它對(duì)應(yīng)的解碼函數(shù)是decodeURIComponent()近弟。

(完)

http://www.ruanyifeng.com/blog/2010/02/url_encoding.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市挺智,隨后出現(xiàn)的幾起案子祷愉,更是在濱河造成了極大的恐慌,老刑警劉巖赦颇,帶你破解...
    沈念sama閱讀 211,423評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件二鳄,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡媒怯,警方通過(guò)查閱死者的電腦和手機(jī)订讼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,147評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)沪摄,“玉大人躯嫉,你說(shuō)我怎么就攤上這事纱烘。” “怎么了祈餐?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,019評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵擂啥,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我帆阳,道長(zhǎng)哺壶,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,443評(píng)論 1 283
  • 正文 為了忘掉前任蜒谤,我火速辦了婚禮山宾,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘鳍徽。我一直安慰自己资锰,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,535評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布阶祭。 她就那樣靜靜地躺著绷杜,像睡著了一般。 火紅的嫁衣襯著肌膚如雪濒募。 梳的紋絲不亂的頭發(fā)上鞭盟,一...
    開(kāi)封第一講書(shū)人閱讀 49,798評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音瑰剃,去河邊找鬼齿诉。 笑死,一個(gè)胖子當(dāng)著我的面吹牛晌姚,可吹牛的內(nèi)容都是我干的粤剧。 我是一名探鬼主播,決...
    沈念sama閱讀 38,941評(píng)論 3 407
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼舀凛,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼俊扳!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起猛遍,我...
    開(kāi)封第一講書(shū)人閱讀 37,704評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤馋记,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后懊烤,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體梯醒,經(jīng)...
    沈念sama閱讀 44,152評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,494評(píng)論 2 327
  • 正文 我和宋清朗相戀三年腌紧,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了茸习。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,629評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡壁肋,死狀恐怖号胚,靈堂內(nèi)的尸體忽然破棺而出籽慢,到底是詐尸還是另有隱情,我是刑警寧澤猫胁,帶...
    沈念sama閱讀 34,295評(píng)論 4 329
  • 正文 年R本政府宣布箱亿,位于F島的核電站,受9級(jí)特大地震影響弃秆,放射性物質(zhì)發(fā)生泄漏届惋。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,901評(píng)論 3 313
  • 文/蒙蒙 一菠赚、第九天 我趴在偏房一處隱蔽的房頂上張望脑豹。 院中可真熱鬧,春花似錦衡查、人聲如沸瘩欺。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,742評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)击碗。三九已至,卻和暖如春们拙,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背阁吝。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,978評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工砚婆, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人突勇。 一個(gè)月前我還...
    沈念sama閱讀 46,333評(píng)論 2 360
  • 正文 我出身青樓装盯,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親甲馋。 傳聞我的和親對(duì)象是個(gè)殘疾皇子埂奈,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,499評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • 關(guān)于URL編碼 一、問(wèn)題的由來(lái) URL就是網(wǎng)址定躏,只要上網(wǎng)账磺,就一定會(huì)用到。 一般來(lái)說(shuō)痊远,URL只能使用英文字母垮抗、阿拉伯...
    奶茶007閱讀 420評(píng)論 0 1
  • 每個(gè) Web 開(kāi)發(fā)者都應(yīng)該知道的關(guān)于 URL 編碼的知識(shí) 原文地址:https://www.oschina.net...
    藍(lán)色緣分1021閱讀 1,138評(píng)論 0 4
  • 一、姓名存儲(chǔ)和展現(xiàn) 1. 按學(xué)生總表編碼存儲(chǔ) 李洋薛鵬磊按照學(xué)生總表進(jìn)行編碼碧聪,并將編碼進(jìn)行存儲(chǔ)或者發(fā)送 左邊是客戶(hù)...
    果芽軟件閱讀 5,111評(píng)論 0 0
  • 一冒版、問(wèn)題的由來(lái) URL就是網(wǎng)址,只要上網(wǎng)逞姿,就一定會(huì)用到辞嗡。 一般來(lái)說(shuō)捆等,URL只能使用英文字母、阿拉伯?dāng)?shù)字和某些標(biāo)點(diǎn)符...
    Jedore閱讀 896評(píng)論 0 0
  • 你的心中 永遠(yuǎn)有一個(gè)人 別人跳舞不去ta 別人唱歌不如ta 別人的笑話(huà)不如ta 別人的手不如ta暖 別人的心不如t...
    _North閱讀 128評(píng)論 0 0