Node.js throws “btoa is not defined” error
在我的node.js应用程序中,我做了一个
但是,由于某种原因,它仍然无法工作。
1 | console.log(btoa("Hello World!")); |
^应该向控制台输出" SGVsbG8gV29ybGQh",但是,我得到了错误:
btoa is not defined.
我没有正确安装吗? 我忽略了什么?
" btoa-atob"模块不导出编程接口,它仅提供命令行实用程序。
如果您需要转换为Base64,可以使用Buffer进行:
1 | console.log(Buffer.from('Hello World!').toString('base64')); |
反向(假设您要解码的内容是utf8字符串):
1 | console.log(Buffer.from(b64Encoded, 'base64').toString()); |
注意:在节点v4之前,请使用
此处发布的解决方案不适用于非ASCII字符(即,如果您计划在Node.js和浏览器之间交换base64)。为了使其正常工作,您必须将输入文本标记为"二进制"。
1 | Buffer.from('Hélló wórld!!', 'binary').toString('base64') |
这使您
1 | Buffer.from('SOlsbPMgd/NybGQhIQ==', 'base64').toString('binary') |
如果不执行"二进制部分",则会错误地解码特殊字符。
我是从btoa npm包的实现中得到的:
我的团队在将Node与React Native和PouchDB一起使用时遇到了这个问题。这是我们解决的方法...
NPM安装缓冲区:
1 | $ npm install --save buffer |
确保
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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'); }; } |
我发现,尽管以上答案中的填充效果都可以,但是它们与桌面浏览器的
1 2 3 4 5 | 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]))); |
事实证明,默认情况下
因此,您需要将编码类型显式设置为
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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]))); |
我在服务器和客户端之间共享一个代码,并且需要在其中实现btoa。
我尝试做类似的事情:
1 | const btoaImplementation = btoa || (str => Buffer.from(str).toString('base64')); |
但是服务器会崩溃:
ReferenceError: btoa is not defined
而
我无法检查window.btoa(这是共享代码,还记得吗?)
因此,我最终完成了该实现:
1 2 3 4 5 6 7 | const btoaImplementation = str => { try { return btoa(str); } catch(err) { return Buffer.from(str).toString('base64') } }; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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(); } }; |
这是针对base64编码的简洁通用解决方案:
1 2 | const nodeBtoa = (b) => Buffer.from(b).toString('base64'); export const base64encode = typeof btoa !== 'undefined' ? btoa : nodeBtoa; |
Atom编辑器中的"脚本"插件存在相同的问题,该插件是旧版本的节点,没有btoa()或atob(),也不支持Buffer数据类型。以下代码可以解决问题:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | var Base64 = new function() { var keyStr ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=" this.encode = function(input) { var output =""; var chr1, chr2, chr3, enc1, enc2, enc3, enc4; var i = 0; input = Base64._utf8_encode(input); 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; } output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) + keyStr.charAt(enc3) + keyStr.charAt(enc4); } return output; } this.decode = function(input) { var output =""; var chr1, chr2, chr3; var enc1, enc2, enc3, enc4; var i = 0; input = 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) | enc4; output = output + String.fromCharCode(chr1); if (enc3 != 64) { output = output + String.fromCharCode(chr2); } if (enc4 != 64) { output = output + String.fromCharCode(chr3); } } output = Base64._utf8_decode(output); return output; } this._utf8_encode = function(string) { string = string.replace(/\ \ /g,"\ "); 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); } } return utftext; } this._utf8_decode = function(utftext) { var string =""; var i = 0; var c = 0, c1 = 0, c2 = 0, c3 = 0; while (i < utftext.length) { c = utftext.charCodeAt(i); if (c < 128) { string += String.fromCharCode(c); i++; } else if ((c > 191) && (c < 224)) { c2 = utftext.charCodeAt(i + 1); string += String.fromCharCode(((c & 31) << 6) | (c2 & 63)); i += 2; } else { c2 = utftext.charCodeAt(i + 1); c3 = utftext.charCodeAt(i + 2); string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); i += 3; } } return string; } }() 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==')); |
我了解这是节点应用程序的讨论点,但是出于在节点服务器上运行的通用JavaScript应用程序的兴趣(这是我到达此职位的方式),我一直在研究通用/同构React应用程序。建筑,而包装
(此包由
回到我的观点;基于此,也许如果该功能已经像您提到的那样已作为npm软件包编写,并且具有基于W3规范的自己的算法,则可以安装和使用
- -编辑 - -
我今天开始用包
也许您不再需要它了,但是如果有人使用节点需要它:
https://www.npmjs.com/package/btoa