解決 Javascript 中 atob 方法解碼中文字符亂碼問題 由於一些網絡通訊協議的限制,你必須使用 window.btoa() 方法對原數據進行編碼后,才能進行發送。接收方使用相當於 window.atob() 的方法對接受到的 base64 數據進行解碼,得到原數據。例如,發送某些含有 ASCII 碼表中 0 到 31 之間的控制字符的數據。 window.btoa 與 window.atob 不支持中文 對於 unicode 編碼的字符進行 base64 編碼之后,通過瀏覽器原生的 btoa 方法界面中文會亂碼。 在 bash 終端,將“中文”轉成 base64 編碼 $ echo 中文 | base64 5Lit5paHCg== 在 Chrome console 通過 window.atob 解碼,結果為亂碼 > window.atob('5Lit5paHCg==') 䏿 在 Chrome console 中執行 windows.btoa 編碼,報錯 > window.btoa('中文') Uncaught DOMException: Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range. 從錯誤提示看, btoa 僅支持 ASCII 編碼。 借助 encodeURIComponent 和 decodeURIComponent 轉義非中文字符 由於 btoa 僅支持 ASCII 字符序列,如果通過 encodeURIComponent 將中文字符編碼成ASCII字符序列,再通過 btoa 進行 base64 編碼。 編碼 > window.btoa(encodeURIComponent('中文')) "JUU0JUI4JUFEJUU2JTk2JTg3" 解碼 > decodeURIComponent(window.atob('JUU0JUI4JUFEJUU2JTk2JTg3')) "中文" 雖然到達了曲線救國的目的,但是由於 encodeURIComponent 和 decodeURIComponent 已經達到了轉義控制字符的目的,使用 atob 和 btoa 感覺是多此一舉。 第三方 Base64 工具 webtoolkit.base64是一個第三方實現的 Base64 編碼工具,完美的支持 unicode 編碼的字符串。 > Base64.encode('中文') "5Lit5paH" > Base64.decode('5Lit5paH'); "中文" 另外,如果服務端為 Nodejs ,可用如下 coffee 代碼進行 base64 的編碼和解碼。 btoa: (s)-> (new Buffer(s, 'utf8')).toString('base64') atob: (s)-> (new Buffer(s, 'base64').toString('utf8')) 參考閱讀 btoa(), atob() 支援中文的方法 How to encode UTF8 characters into Base64 in JavaScript window.atob Best practice: escape, or encodeURI / encodeURIComponent
值得一提的是
某些情況下需要用 window.btoa(unescape(encodeURIComponent(svg1)));
JavaScript unescape() 和 escape() 函數
提示和注釋
注釋:ECMAScript v3 已從標准中刪除了 unescape() 函數,並反對使用它,因此應該用 decodeURI() 和 decodeURIComponent() 取而代之。
詳見:https://www.w3school.com.cn/jsref/jsref_unescape.asp
補充:
還可以通過如下方式 解析base64 (但這個base64中 如果含有中文,我這里以前后端為例子)
假如 base64 中含有中文,后端通過 第三方庫編碼,前端再不用第三方庫的情況下可以這樣解碼,並且中文不亂碼,
具體實現如下:
function base64ToArrayBuffer(base64) { var binary_string = window.atob(base64); var len = binary_string.length; var bytes = new Uint8Array(len); for (var i = 0; i < len; i++) { bytes[i] = binary_string.charCodeAt(i); } return bytes.buffer; } let hahahaBase64 = "e+WTiOWTiOWTiH0="; // 通過第三方庫 "{哈哈哈}" 轉出 base64 而 不是 window.btoa() // 直接 window.atob() console.log(window.atob(hahahaBase64)); // {ååå} // 解碼后 通過 二進制數據緩沖區 console.log(new Blob([base64ToArrayBuffer(hahahaBase64)]).text()); // [[PromiseResult]]: "{哈哈哈}"