在我的 node.js 应用程序中,我做了一个 npm install btoa-atob
,以便我可以使用客户端 javascript 中本机的 btoa()
和 atob()
函数,但由于某种原因未包含在 node.js 中。新目录出现在我的 node_modules
文件夹中,该文件夹本身位于 app.js
旁边的根目录中。然后我确保将 btoa-atob 作为依赖项添加到我的根目录中的 package.json
文件中。
但是,由于某种原因,它仍然无法正常工作。
console.log(btoa("Hello World!"));
应该将“SGVsbG8gV29ybGQh”输出到控制台,但是,我得到了错误:
btoa 未定义。
我没有正确安装吗?我忽略了什么?
'btoa-atob' 模块不导出编程接口,它只提供命令行实用程序。
如果您需要转换为 Base64,您可以使用 Buffer 进行转换:
console.log(Buffer.from('Hello World!').toString('base64'));
反向(假设您正在解码的内容是一个 utf8 字符串):
console.log(Buffer.from(b64Encoded, 'base64').toString());
注意:在 Node v4 之前,使用 new Buffer
而不是 Buffer.from
。
此处发布的解决方案不适用于非 ascii 字符(即,如果您计划在 Node.js 和浏览器之间交换 base64)。为了使其工作,您必须将输入文本标记为“二进制”。
Buffer.from('Hélló wórld!!', 'binary').toString('base64')
这为您提供 SOlsbPMgd/NybGQhIQ==
。如果您在浏览器中制作 atob('SOlsbPMgd/NybGQhIQ==')
,它将以正确的方式对其进行解码。它也可以通过以下方式在 Node.js 中正确执行:
Buffer.from('SOlsbPMgd/NybGQhIQ==', 'base64').toString('binary')
如果你不做“二进制部分”,你会错误地解码特殊字符。
我明白了from the implementation of the btoa npm package:
我的团队在使用带有 React Native 和 PouchDB 的 Node 时遇到了这个问题。以下是我们如何解决它...
NPM 安装缓冲区:
$ npm install --save buffer
确保 Buffer
、btoa
和 atob
作为全局变量加载:
global.Buffer = global.Buffer || require('buffer').Buffer;
if (typeof btoa === 'undefined') {
global.btoa = function (str) {
return new Buffer(str, 'binary').toString('base64');
};
}
if (typeof atob === 'undefined') {
global.atob = function (b64Encoded) {
return new Buffer(b64Encoded, 'base64').toString('binary');
};
}
export const universalBtoa = str => {
try {
return btoa(str);
} catch (err) {
return Buffer.from(str).toString('base64');
}
};
export const universalAtob = b64Encoded => {
try {
return atob(b64Encoded);
} catch (err) {
return Buffer.from(b64Encoded, 'base64').toString();
}
};
Buffer.from(b64Encoded, 'base64').toString('binary');
,如 stackoverflow.com/a/47890385/470749,universalAtob 才对我有用
我发现虽然上述答案中的垫片有效,但它们与桌面浏览器的 btoa()
和 atob()
实现的行为不匹配:
const btoa = function(str){ return Buffer.from(str).toString('base64'); }
// returns "4pyT", yet in desktop Chrome would throw an error.
btoa('✓');
// returns "fsO1w6bCvA==", yet in desktop Chrome would return "fvXmvA=="
btoa(String.fromCharCode.apply(null, new Uint8Array([0x7e, 0xf5, 0xe6, 0xbc])));
事实证明,Buffer
实例表示/解释以 UTF-8 by default 编码的字符串。相比之下,在桌面版 Chrome 中,您甚至不能将包含 latin1 范围之外的字符的字符串输入 btoa()
,因为它会抛出异常:Uncaught DOMException: Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range.
因此,您需要将 encoding type 显式设置为 latin1
,以便您的 Node.js shim 匹配桌面 Chrome 的编码类型:
const btoaLatin1 = function(str) { return Buffer.from(str, 'latin1').toString('base64'); }
const atobLatin1 = function(b64Encoded) {return Buffer.from(b64Encoded, 'base64').toString('latin1');}
const btoaUTF8 = function(str) { return Buffer.from(str, 'utf8').toString('base64'); }
const atobUTF8 = function(b64Encoded) {return Buffer.from(b64Encoded, 'base64').toString('utf8');}
btoaLatin1('✓'); // returns "Ew==" (would be preferable for it to throw error because this is undecodable)
atobLatin1(btoa('✓')); // returns "\u0019" (END OF MEDIUM)
btoaUTF8('✓'); // returns "4pyT"
atobUTF8(btoa('✓')); // returns "✓"
// returns "fvXmvA==", just like desktop Chrome
btoaLatin1(String.fromCharCode.apply(null, new Uint8Array([0x7e, 0xf5, 0xe6, 0xbc])));
// returns "fsO1w6bCvA=="
btoaUTF8(String.fromCharCode.apply(null, new Uint8Array([0x7e, 0xf5, 0xe6, 0xbc])));
Buffer.from()
是使用 Buffer API 的 recommended way(尽管该链接将阐明可能适用于 Node v0.12.2 的 Buffer.from()
的替代方案)。
我在服务器和客户端之间共享了一个代码,我需要在其中实现 btoa。我尝试做类似的事情:
const btoaImplementation = btoa || (str => Buffer.from(str).toString('base64'));
但服务器会粉碎:
ReferenceError: btoa 未定义
而 Buffer
未在客户端上定义。
我无法检查 window.btoa(这是共享代码,记得吗?)
所以我最终得到了这个实现:
const btoaImplementation = str => {
try {
return btoa(str);
} catch(err) {
return Buffer.from(str).toString('base64')
}
};
Atom 编辑器中的“脚本”插件也有同样的问题,它是节点的旧版本,没有 btoa(),也没有 atob(),也不支持 Buffer 数据类型。以下代码可以解决问题:
var Base64 = new function() { var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=" this.encode = function(input) { var output = ""; var chr1,chr2,chr3,enc1,enc2,enc3,enc4;变量 i = 0;输入 = Base64._utf8_encode(输入); while (i < input.length) { chr1 = input.charCodeAt(i++); chr2 = input.charCodeAt(i++); chr3 = input.charCodeAt(i++); enc1 = chr1 >> 2; enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); enc4 = chr3 & 63; if (isNaN(chr2)) { enc3 = enc4 = 64; } else if (isNaN(chr3)) { enc4 = 64; } 输出 = 输出 + keyStr.charAt(enc1) + keyStr.charAt(enc2) + keyStr.charAt(enc3) + keyStr.charAt(enc4); } 返回输出; } this.decode = function(input) { var output = ""; var chr1,chr2,chr3; var enc1,enc2,enc3,enc4;变量 i = 0;输入 = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); while (i < input.length) { enc1 = keyStr.indexOf(input.charAt(i++)); enc2 = keyStr.indexOf(input.charAt(i++)); enc3 = keyStr.indexOf(input.charAt(i++)); enc4 = keyStr.indexOf(input.charAt(i++)); chr1 = (enc1 << 2) | (enc2 >> 4); chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); chr3 = ((enc3 & 3) << 6) |编码4;输出 = 输出 + String.fromCharCode(chr1); if (enc3 != 64) { 输出 = 输出 + String.fromCharCode(chr2); } if (enc4 != 64) { 输出 = 输出 + String.fromCharCode(chr3); } } 输出 = Base64._utf8_decode(输出);返回输出; } this._utf8_encode = function(string) { string = string.replace(/\r\n/g, "\n"); var utftext = ""; for (var n = 0; n < string.length; n++) { var c = string.charCodeAt(n); if (c < 128) { utftext += String.fromCharCode(c); } else if ((c > 127) && (c < 2048)) { utftext += String.fromCharCode((c >> 6) | 192); utftext += String.fromCharCode((c & 63) | 128); } else { utftext += String.fromCharCode((c >> 12) | 224); utftext += String.fromCharCode(((c >> 6) & 63) | 128); utftext += String.fromCharCode((c & 63) | 128); } } 返回 utftext; } this._utf8_decode = function(utftext) { var string = "";变量 i = 0;变量 c = 0, c1 = 0, c2 = 0, c3 = 0; while (i < utftext.length) { c = utftext.charCodeAt(i); if (c < 128) { string += String.fromCharCode(c);我++; } else if ((c > 191) && (c < 224)) { c2 = utftext.charCodeAt(i + 1);字符串 += String.fromCharCode(((c & 31) << 6) | (c2 & 63));我 += 2; } else { c2 = utftext.charCodeAt(i + 1); c3 = utftext.charCodeAt(i + 2); string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));我+= 3; } } 返回字符串; } }() var btoa = Base64.encode; var atob = Base64.decode; console.log("btoa('A') = " + btoa('A')); console.log("btoa('QQ==') = " + atob('QQ==')); console.log("btoa('B') = " + btoa('B')); console.log("btoa('Qg==') = " + atob('Qg=='));
这是base64编码的简洁通用解决方案:
const nodeBtoa = (b) => Buffer.from(b).toString('base64');
export const base64encode = typeof btoa !== 'undefined' ? btoa : nodeBtoa;
我能够使用以下 npm 包将 btoa
用于二进制数据到 base 64 字符串的转换:https://www.npmjs.com/package/btoa
如他们的文档中所述,我在节点 JS 应用程序中执行了以下步骤:
安装 => npm install --save btoa 在顶部声明 => const btoa = require('btoa');使用 => const b64 = btoa("stringToEncode");
任何想要解码的人:
let decoded = Buffer.from(<encoded string>, 'base64').toString()
。
因为我来这里是为了寻找解码,所以最终从这里的答案中弄清楚了。
我知道这是一个节点应用程序的讨论点,但是为了通用 JavaScript 应用程序在节点服务器上运行,这就是我到达这篇文章的方式,我一直在研究这个以获取通用/ 我一直在构建的同构反应应用程序,包 abab
为我工作。事实上,这是我能找到的唯一可行的解决方案,而不是使用提到的 Buffer 方法(我遇到了打字稿问题)。
(此包由 jsdom
使用,而后者又由 window
包使用。)
回到我的观点;基于此,也许如果这个功能已经像你提到的那样写成一个 npm 包,并且有它自己的基于 W3 规范的算法,你可以安装和使用 abab
包而不是编写你自己的函数可能或根据编码可能不准确。
- -编辑 - -
我今天开始在使用包 abab
的编码(不知道为什么现在开始发生)方面遇到奇怪的问题。它似乎大部分时间都正确编码,但有时在前端它编码不正确。花了很长时间尝试调试,但按照建议切换到包 base-64
,它立即工作。绝对似乎归结为 abab
的 base64 算法。
如果你最终来到这里,寻找 atob 不是定义的解决方案(像我一样)。尝试升级你的 nodejs 版本 - 它对我有帮助
Buffer.from('Hélló wórld!!').toString('base64')
- 它会给你SOlsbPMgd/NybGQhIQ==
可以正确转换为非 ascii 字符串。atob(btoa("Hélló wórld!!")) === "Hélló wórld!!"
b)在节点 10 中:Buffer.from('Hélló wórld!!').toString('base64') === 'SMOpbGzDsyB3w7NybGQhIQ=='
和Buffer.from('SMOpbGzDsyB3w7NybGQhIQ==', 'base64').toString() === 'Hélló wórld!!'
c)节点的Buffer.from()
可以读取,即使您删除尾随 '=',但您始终可以编写简单的函数用尾随'='完成编码字符串。SMOpbGzDsyB3w7NybGQhIQ==
。如果您在浏览器中对此进行解码,它将为您提供Hélló wórld!!
。该二进制文件非常适合确保跨平台兼容性。function btoa(str){return Buffer.from(str, 'binary').toString('base64');}
function atob(str){return Buffer.from(str, 'base64').toString('binary');}