(造福中國前端界)純前端Js完美解決各種漢字urlencode,urldecode,編碼解碼問題,不借助任何字庫,內碼表,輕松一行,兼容IE8+,chrome,firefox,safari等主流瀏覽器


最后補充一下:IE6,7用vbscript可以decode,傳送門:http://www.baidu.com/s?wd=vbscript+urldecode+gbk

(昨晚更新)IE8是不支持script的src的datauri的,昨晚想了一個hack方法

MSND傳送門:http://msdn.microsoft.com/en-us/library/cc848897(v=vs.85).aspx

IE8支持link的datauri,我想是否可以構造一個link過來的css,通過設置background-image,然后通過ie的currentStyle[‘backgroundImage’]取到中文

image

這里定義了一個隱藏的元素,通過datauri方式引入css,然后應用,即可以通過js獲得該背景圖src,測試IE8通過(2013.5.31早更新)

我們都知道javascript在做表單提交的時候,會遇到很多坑爹的 中文需要轉換成gbk encode或者big5 encode的問題,

比如 中文的

javascript原生的escape只是將中文轉換為unicode編碼,encodeURI或者encodeURIComponent也是對於中文unicode編碼的url再編碼

對於“中文”這個漢字來說,他的utf-8的urlencode是%E4%B8%AD%E6%96%87,而gbk的urlencode是%D6%D0%CE%C4

而js本身沒有特性支持gbk的urlencode,大部分的時候我們是通過后台(java,urlencode.encode(“中文”,”gbk”))這樣來實現的

本文介紹一個借助瀏覽器,純前端實現各種編碼集的urlencode方式和decode方法

demo地址:http://xueduany.github.io/KitJs/urlencode.html,(這個包含了 解碼,編碼方法)

http://xueduany.github.io/KitJs/getEncodeStr.html(這個用來iframe回調解碼后的值的文件)

image

chrome,firefox,safari測試通過,移動端均可,IE10以下下面會另說

 

(一) 編碼原理

function urlencode(str, charset, callback) {
            //創建form通過accept-charset做encode
            var form = document.createElement('form');
            form.method = 'get';
            form.style.display = 'none';
            form.acceptCharset = charset;
            var input = document.createElement('input');
            input.type = 'hidden';
            input.name = 'str';
            input.value = str;
            form.appendChild(input);
            form.target = '_urlEncode_iframe_';
            document.body.appendChild(form);
            //隱藏iframe截獲提交的字符串
            if (!window['_urlEncode_iframe_']) {
                var iframe = document.createElement('iframe');
                //iframe.name = '_urlEncode_iframe_';
                iframe.setAttribute('name', '_urlEncode_iframe_');
                iframe.style.display = 'none';
                iframe.width = "0";
                iframe.height = "0";
                iframe.scrolling = "no";
                iframe.allowtransparency = "true";
                iframe.frameborder = "0";
                iframe.src = 'about:blank';
                document.body.appendChild(iframe);
            }
            //
            window._urlEncode_iframe_callback = callback;
            //設置回調編碼頁面的地址,這里需要用戶修改
            form.action = 'getEncodeStr.html';
            form.submit();
            setTimeout(function() {
                form.parentNode.removeChild(form);
                iframe.parentNode.removeChild(iframe);
            }, 500)

        }

通過HTML元素form自帶屬性accept-charset在表單提交發送數據時候,瀏覽器會根據這個屬性值做自動urlencode,get/post方式均可

accept-charset 屬性規定服務器處理表單數據所接受的字符集。

accept-charset 屬性允許您指定一系列字符集,服務器必須支持這些字符集,從而得以正確解釋表單中的數據。

該屬性的值是用引號包含字符集名稱列表。如果可接受字符集與用戶所使用的字符即不相匹配的話,瀏覽器可以選擇忽略表單或是將該表單區別對待。

瀏覽器支持

除了 Internet Explorer,accept-charset 屬性得到幾乎所有瀏覽器的支持。

注釋:accept-charset 屬性無法在 Internet Explorer 中正確地工作。如果 accept-charset 屬性設置為 "ISO-8859-1",IE 將發送以 "Windows-1252" 編碼的數據。

語法

<form accept-charset="value">

從例子的代碼,我們巧妙的利用了這個屬性,構造一個接受gbk encode之后url的頁面,通過location.search獲取到encode之后的編碼,再傳遞給原頁面,即可實現對於任意字符的任意編碼urlencode

 

(二)解碼

上面說了編碼,現在說說 如果我們獲得一串%D6%D0%CE%C4,而且我們知道這個是gbk編碼的,那么我們如何得到這個編碼的中文呢?

function urldecode(str, charset, callback) {
            window._urlDecodeFn_ = callback;
            var script = document.createElement('script');
            script.id = '_urlDecodeFn_';
            var src = 'data:text/javascript;charset=' + charset + ',_urlDecodeFn_("' + str + '");'
            src += 'document.getElementById("_urlDecodeFn_").parentNode.removeChild(document.getElementById("_urlDecodeFn_"));';
            script.src = src;
            document.body.appendChild(script);
        }

這個問題的核心在於編碼是urlencdoe的,那么除了utf-8格式的我們可以借助js自己的decodeURI等之后,對於gbk的,我們一般是無能為力的

這里巧妙構造了一個URI資源,因為通過URI方式引入的script,可以指定字符編碼的,而瀏覽器會根據指定的字符編碼,做urldecode,這樣就實現了我們想要的urldecode效果

(三)IE

最后,我們來看看比較郁悶的IE,對於IE來說,他完全不認我們的form的accept-charset屬性,他們的表單提交的編碼格式,是按照頁面的meta制定的字符集來的,當然了,他也給廣大屌絲前端留了一條后路,就是他們的document.charset屬性,是可讀可寫的,

而且IE為了表現它確實是一傻到底,不但在設置document.charset的時候不會用新的編碼解釋頁面,還會在前進后退(我特地用#作為action來實現后退)的時候又嘗試用新的編碼去解釋頁面。

所以我們需要hook之前的編碼,在解碼后再轉換回來

function urlencode(str, charset, callback) {
            //創建form通過accept-charset做encode
            var form = document.createElement('form');
            form.method = 'get';
            form.style.display = 'none';
            form.acceptCharset = charset;
            if (document.all) {
                //如果是IE那么就調用document.charset方法
                window.oldCharset = document.charset;
                document.charset = charset;
            }
            var input = document.createElement('input');
            input.type = 'hidden';
            input.name = 'str';
            input.value = str;
            form.appendChild(input);
            form.target = '_urlEncode_iframe_';
            document.body.appendChild(form);
            //隱藏iframe截獲提交的字符串
            if (!window['_urlEncode_iframe_']) {
                var iframe = document.createElement('iframe');
                //iframe.name = '_urlEncode_iframe_';
                iframe.setAttribute('name', '_urlEncode_iframe_');
                iframe.style.display = 'none';
                iframe.width = "0";
                iframe.height = "0";
                iframe.scrolling = "no";
                iframe.allowtransparency = "true";
                iframe.frameborder = "0";
                iframe.src = 'about:blank';
                document.body.appendChild(iframe);
            }
            //
            window._urlEncode_iframe_callback = function(str) {
                callback(str);
                if (document.all) {
                    document.charset = window.oldCharset;
                }
            }
            //設置回調編碼頁面的地址,這里需要用戶修改
            form.action = 'getEncodeStr.html';
            form.submit();
            setTimeout(function() {
                form.parentNode.removeChild(form);
                iframe.parentNode.removeChild(iframe);
            }, 500)

        }
        function urldecode(str, charset, callback) {
            var script = document.createElement('script');
            script.id = '_urlDecodeFn_';
            window._urlDecodeFn_ = callback;
            if (document.all) {
                //隱藏iframe截獲提交的字符串
                if (!window['_urlDecode_iframe_']) {
                    var iframe = document.createElement('iframe');
                    //iframe.name = '_urlDecode_iframe_';
                    iframe.setAttribute('name', '_urlDecode_iframe_');
                    iframe.style.display = 'none';
                    iframe.width = "0";
                    iframe.height = "0";
                    iframe.scrolling = "no";
                    iframe.allowtransparency = "true";
                    iframe.frameborder = "0";
                    iframe.src = 'about:blank';
                    document.body.appendChild(iframe);
                }
                //ie下需要指明charset,然后src=datauri才可以
                iframe.contentWindow.document.write('<html><scrip' + 't charset="gbk" src="data:text/javascript;charset=gbk,parent._decodeStr_=\'' + str + '\'"></s'+'cript></html>');
                setTimeout(function() {
                    callback(_decodeStr_);
                    iframe.parentNode.removeChild(iframe);
                }, 300)
            } else {
                var src = 'data:text/javascript;charset=' + charset + ',_urlDecodeFn_("' + str + '");';
                src += 'document.getElementById("_urlDecodeFn_").parentNode.removeChild(document.getElementById("_urlDecodeFn_"));';
                script.src = src;
                document.body.appendChild(script);
            }
        }

關鍵點在於,編碼時

image

解碼時的關鍵在與,對於支持datauri版本的ie,不僅僅在於datauri里面制定編碼集,還在在script的charset上指定編碼

image

這樣就可以實現瀏覽器的完美兼容

(四)小結

再次感謝騰訊前端QQ群的各位,沒有你們的建議和支持,不會想到這么好的解決方案,再次感謝大家,希望看到的廣大的前端屌絲們大力擴散,早日每一個jser都知道這一特大喜訊!!!哈哈哈哈哈

程序源代碼地址:

https://github.com/xueduany/KitJs/blob/gh-pages/urlencode.html

https://github.com/xueduany/KitJs/blob/gh-pages/getEncodeStr.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM