Node.js throws "btoa is not defined" error

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

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'.

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:

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:


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

NPM install buffer:

$ npm install --save buffer

Ensure Buffer, btoa, and atob are loaded as a globals:

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

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

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

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

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

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

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

Tags:

Node.Js