Node.js 抛出“btoa 未定义”错误

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23097928/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 17:09:35  来源:igfitidea点击:

Node.js throws "btoa is not defined" error

node.js

提问by Joey

In my node.js application I did an npm install btoa-atobso that I could use the btoa() and atob() functions which are native in client-side javascript but for some reason weren't included in node. The new directory showed up in my node_modules folder, which itself is in root alongside app.js. Then I made sure to add btoa-atob as a dependency in my package.json file which is in root.

在我的 node.js 应用程序中,我做了一个,npm install btoa-atob以便我可以使用客户端 javascript 中原生的 btoa() 和 atob() 函数,但由于某种原因没有包含在node.js中。新目录出现在我的 node_modules 文件夹中,该文件夹本身位于 app.js 旁边的根目录中。然后我确保在根目录下的 package.json 文件中添加 btoa-atob 作为依赖项。

However, for some reason, it still will not work.

但是,由于某种原因,它仍然不起作用。

console.log(btoa("Hello World!"));

^ should output "SGVsbG8gV29ybGQh" to the console, but instead, I get the error "btoa is not defined."

^ 应该将“SGVsbG8gV29ybGQh”输出到控制台,但相反,我收到错误“btoa 未定义”。

Did I not do the install properly? What did I overlook?

我没有正确安装吗?我忽略了什么?

回答by mscdex

The 'btoa-atob' module does not export a programmatic interface, it only provides command line utilities.

'btoa-atob' 模块不导出编程接口,它只提供命令行实用程序。

If you need to convert to Base64 you could do so using Buffer:

如果您需要转换为 Base64,您可以使用 Buffer:

console.log(Buffer.from('Hello World!').toString('base64'));

Reverse (assuming the content you're decoding is a utf8 string):

反向(假设您正在解码的内容是 utf8 字符串):

console.log(Buffer.from(b64Encoded, 'base64').toString());


Note: prior to Node v4, use new Bufferrather than Buffer.from.

注意:在 Node v4 之前,使用new Buffer而不是Buffer.from.

回答by Iván Alegre

The solutions posted here don't work in non-ascii characters (i.e. if you plan to exchange base64 between Node.js and a browser). In order to make it work you have to mark the input text as 'binary'.

此处发布的解决方案不适用于非 ascii 字符(即,如果您打算在 Node.js 和浏览器之间交换 base64)。为了使其工作,您必须将输入文本标记为“二进制”。

Buffer.from('Hélló wórld!!', 'binary').toString('base64')

This gives you SOlsbPMgd/NybGQhIQ==. If you make atob('SOlsbPMgd/NybGQhIQ==')in a browser it will decode it in the right way. It will do it right also in Node.js via:

这给你SOlsbPMgd/NybGQhIQ==。如果您atob('SOlsbPMgd/NybGQhIQ==')在浏览器中制作,它将以正确的方式对其进行解码。它也可以通过以下方式在 Node.js 中正确执行:

Buffer.from('SOlsbPMgd/NybGQhIQ==', 'base64').toString('binary')

If you don't do the "binary part", you will decode wrongly the special chars.

如果你不做“二进制部分”,你会错误地解码特殊字符。

I got it from the implementation of the btoa npm package:

从 btoa npm 包的实现中得到它:

回答by PaulMest

My team ran into this problem when using Node with React Native and PouchDB. Here is how we solved it...

我的团队在将 Node 与 React Native 和 PouchDB 结合使用时遇到了这个问题。这是我们如何解决它...

NPM install buffer:

NPM 安装缓冲区:

$ npm install --save buffer

Ensure Buffer, btoa, and atobare loaded as a globals:

确保Bufferbtoaatob作为全局变量加载:

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');
  };
}

回答by Jamie Birch

I found that although the shims from answers above worked, they did not match the behaviour of desktop browsers' implementations of btoa()and atob():

我发现尽管上述答案中的垫片有效,但它们与桌面浏览器的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])));

As it turns out, Bufferinstances represent/interpret strings encoded in UTF-8 by default. By contrast, in desktop Chrome, you can't even input a string that contains characters outside of the latin1 range into btoa(), as it will throw an exception: Uncaught DOMException: Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range.

事实证明,Buffer实例表示/解释默认情况下以 UTF-8 编码的字符串。相比之下,在桌面 Chrome 中,您甚至不能将包含 latin1 范围之外的字符的字符串输入到 中btoa(),因为它会抛出异常:Uncaught DOMException: Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range.

Therefore, you need to explicitly set the encoding typeto latin1in order for your Node.js shim to match the encoding type of desktop Chrome:

因此,您需要将编码类型显式设置为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])));

回答by Alexander

I have a code shared between server and clientand I needed an implementation of btoa inside it. I tried doing something like:

我有一个在服务器和客户端之间共享的代码,我需要在其中实现 btoa。我尝试做类似的事情:

const btoaImplementation =  btoa || (str => Buffer.from(str).toString('base64'));

but the Server would crush with:

但服务器会粉碎:

ReferenceError: btoa is not defined

ReferenceError: btoa 未定义

while Bufferis not defined on the client.

whileBuffer未在客户端上定义。

I couldn't check window.btoa (it's a shared code, remember?)

我无法检查 window.btoa(这是一个共享代码,还记得吗?)

So I ended up with this implementation:

所以我最终得到了这个实现:

const btoaImplementation = str => {
    try {
        return btoa(str);
    } catch(err) {
        return Buffer.from(str).toString('base64')
    }
};

回答by ali eslamifard

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();
  }
};

回答by Phil Gibbins

I understand this is a discussion point for a node application, but in the interest of universal JavaScript applicationsrunning on a node server, which is how I arrived at this post, I have been researching this for a universal / isomorphic react app I have been building, and the package ababworked for me. In fact it was the only solution I could find that worked, rather than using the Buffer method also mentioned (I had typescript issues).

我知道这是一个节点应用程序的讨论点,但为了在节点服务器上运行的通用 JavaScript 应用程序的利益,这就是我到达这篇文章的方式,我一直在研究这个我一直在研究的通用/同构反应应用程序构建,并且该软件包abab对我有用。事实上,这是我能找到的唯一可行的解​​决方案,而不是使用也提到的 Buffer 方法(我有打字稿问题)。

(This package is used by jsdom, which in turn is used by the windowpackage.)

(此包由 使用jsdom,而后者又由window包使用。)

Getting back to my point; based on this, perhaps if this functionality is already written as an npm package like the one you mentioned, and has it's own algorithm based on W3 spec, you could install and use the ababpackage rather than writing you own function that may or may not be accurate based on encoding.

回到我的观点;基于此,也许如果此功能已经像您提到的那样编写为 npm 包,并且具有基于 W3 规范的自己的算法,则您可以安装和使用该abab包,而不是编写自己的函数,这些函数可能是也可能不是准确基于编码。

---EDIT---

---编辑---

I started having weird issues today with encoding (not sure why it's started happening now) with package abab. It seems to encode correctly most of the time, but sometimes on front end it encodes incorrectly. Spent a long time trying to debug, but switched to package base-64as recommended, and it worked straight away. Definitely seemed to be down to the base64 algorithm of abab.

我今天开始在 package 的编码方面遇到奇怪的问题(不知道为什么现在开始发生)abab。大多数时候它似乎编码正确,但有时在前端编码不正确。花了很长时间尝试调试,但base-64按照建议切换到包,它立即起作用。绝对似乎归结为abab.

回答by edilson14

Maybe you don't need it anymore but if someone needs this using node: https://www.npmjs.com/package/btoa

也许你不再需要它了,但如果有人需要它使用节点:https: //www.npmjs.com/package/btoa

回答by Shrimpy

Same problem with the 'script' plugin in the Atom editor, which is an old version of node, not having btoa(), nor atob(), nor does it support the Buffer datatype. Following code does the trick:

与 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;
    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(/\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);
      }
    }
    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=='));