解决 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'))

参考阅读

  1. btoa(), atob() 支援中文的方法
  2. How to encode UTF8 characters into Base64 in JavaScript
  3. window.atob
  4. Best practice: escape, or encodeURI / encodeURIComponent

Vangie Du

将来的你,一定会感谢现在拼命努力的自己!

Javascript 中 atob/btoa的更多相关文章

  1. Javascript中Base64编码解码的使用实例

    Javascript为我们提供了一个简单的方法来实现字符串的Base64编码和解码,分别是window.btoa()函数和window.atob()函数. 1 var encodedStr = win ...

  2. JavaScript中七种数据类型·中·一

    Standing on Shoulders of Giants; 说到JavaScript里的类型很容易就让人想起 42和"42",分别是string型和number型,但是他们可 ...

  3. javascript中的Array对象 —— 数组的合并、转换、迭代、排序、堆栈

    Array 是javascript中经常用到的数据类型.javascript 的数组其他语言中数组的最大的区别是其每个数组项都可以保存任何类型的数据.本文主要讨论javascript中数组的声明.转换 ...

  4. javascript中的this与函数讲解

    前言 javascript中没有块级作用域(es6以前),javascript中作用域分为函数作用域和全局作用域.并且,大家可以认为全局作用域其实就是Window函数的函数作用域,我们编写的js代码, ...

  5. JavaScript 中的数据类型

    Javascript中的数据类型有以下几种情况: 基本类型:string,number,boolean 特殊类型:undefined,null 引用类型:Object,Function,Date,Ar ...

  6. javascript中的操作符详解1

    好久没有写点什么了,根据博主的技术,仍然写一点javascript新手入门文章,接下来我们一起来探讨javascript的操作符. 一.前言 javascript中有许多操作符,但是许多初学者并不理解 ...

  7. 掌握javascript中的最基础数据结构-----数组

    这是一篇<数据结构与算法javascript描述>的读书笔记.主要梳理了关于数组的知识.部分内容及源码来自原作. 书中第一章介绍了如何配置javascript运行环境:javascript ...

  8. javascript中变量提升的理解

    网上找了两个经典的例子 var foo = 1; function bar() { if (!foo) { var foo = 10; } alert(foo); } bar(); // 10 var ...

  9. 前端开发:面向对象与javascript中的面向对象实现(二)构造函数与原型

    前端开发:面向对象与javascript中的面向对象实现(二)构造函数与原型 前言(题外话): 有人说拖延症是一个绝症,哎呀治不好了.先不说这是一个每个人都多多少少会有的,也不管它究竟对生活有多么大的 ...

随机推荐

  1. Nginx自定义扩展模块

    1. 概述 参考 Nginx开发HTTP模块入门 2. 扩展模块(假设根目录名称为nginx) nginx/configure文件中可以修改配置文件路径(编译时使用): 例如像把配置文件从默认的ngi ...

  2. Web Server 在iis上部署webservice基于oracle

    在iis上部署webservice基于oracle 常见错误及解决方案: 原因: 先安装.netframework后安装iis造成的: 解决方案: 1.C:\Windows\Microsoft.NET ...

  3. Android应用开发以及设计思想深度剖析

    Android应用开发以及设计思想深度剖析(1) 21cnbao.blog.51cto.com/109393/956049

  4. 二十六、Nodejs 操作 MongoDb 数据库

    一. 在 Nodejs 中使用 Mongodb 前面的课程我们讲了用命令操作 MongoDB,这里我们看下如何用 nodejs 来操作数据库需要引包: npm install mongodb --sa ...

  5. OCP认证052考试最新考试题库和答案整理-33

    33.Where Is backup metadata stored for use by Recovery Manager (RMAN)? A) In the control file B) In ...

  6. “全栈2019”Java第三十九章:构造函数、构造方法、构造器

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  7. TCP的坚持定时器

    一.简介 TCP不对ACK报文段进行确认,TCP只确认那些包含有数据的ACK字段. 如果一个确认丢失了,双方就有可能因为等待对方而使得链连接终止: 接收方等待接受数据,因为已经向发送方通告了一个非0的 ...

  8. c语言-学生成绩信息系统

    #include<stdio.h> #define N 100 int Count=0; struct stu { int num; char name[20]; int computer ...

  9. 将SQLAlchemy对象转化为dict

    需求一,将数据对象转为dict,但是不包括relation, import BaseClass #所有模型的基础类 def getDictFromObj_nr(obj): return_dict={} ...

  10. 851 AlvinZH的鬼畜密码(背包DP大作战N)

    851 AlvinZH的鬼畜密码 思路 难题.动态规划. 先判断字符串是否合理(可翻译),然后分段处理,每一小段用动态规划求出解法数. dp[i]:字符串str[0~i]的解法数.通过判断str[i] ...