Node.js - ошибка "btoa не определена"

В моем приложении node.js я сделал npm install btoa-atob, чтобы использовать функции btoa() и atob(), которые являются родными в клиентском javascript, но по какой-то причине не были включены в node. Новый каталог появился в моей папке node_modules, которая сама находится в корне вместе с app.js. Затем я обязательно добавил btoa-atob в качестве зависимости в моем файле package.json, который находится в корне.

Однако по какой-то причине он все равно не будет работать.

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

^ должен выводить "SGVsbG8gV29ybGQh" на консоль, но вместо этого я получаю ошибку "btoa не defiend".

Не правильно ли я установил установку? Что я пропустил?

Ответ 1

Модуль '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.

Ответ 2

Приведенные здесь решения не работают в не-ascii символах (т.е. если вы планируете обмен base64 между Node.js и браузером). Чтобы заставить его работать, вы должны пометить входной текст как "двоичный".

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

Это дает тебе SOlsbPMgd/NybGQhIQ==. Если вы сделаете atob('SOlsbPMgd/NybGQhIQ==') в браузере, он будет правильно декодирован. Это будет сделано правильно и в Node.js через:

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

Если вы не выполняете "двоичную часть", вы будете неправильно декодировать специальные символы.

Я получил это из реализации пакета btoa npm:

Ответ 3

Моя команда столкнулась с этой проблемой при использовании Node с React Native и PouchDB. Вот как мы решили это...

Буфер установки 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');
  };
}

Ответ 4

Я обнаружил, что, хотя шайбы из приведенных выше ответов сработали, они не соответствовали поведению реализаций настольных браузеров 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 по умолчанию. Напротив, в настольном Chrome вы даже не можете ввести строку, содержащую символы вне диапазона latin1, в btoa(), так как это вызовет исключение: Uncaught DOMException: Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range.

Следовательно, вам нужно явно установить тип кодировки на latin1, чтобы шайба Node.js соответствовала типу кодировки настольного 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])));

Ответ 5

Я понимаю, что это является предметом обсуждения для приложения узла, но в интересах универсальных приложений JavaScript, работающих на сервере узла, и именно так я дошел до этого поста, я исследовал это для универсального/Приложение изоморфной реакции, которое я создавал, и пакет abab работал для меня. На самом деле это было единственное решение, которое я смог найти, и оно работало, вместо того, чтобы использовать метод Buffer, о котором я упоминал (у меня были проблемы с машинописью).

(Этот пакет используется jsdom, который, в свою очередь, используется пакетом window.)

Возвращаясь к моей точке зрения; Исходя из этого, возможно, если эта функциональность уже написана в виде пакета npm, подобного тому, который вы упомянули, и имеет собственный алгоритм, основанный на спецификации W3, вы можете установить и использовать пакет abab вместо того, чтобы писать собственную функцию, которая может или может быть неточным в зависимости от кодировки.

---EDIT ---

Сегодня у меня начались странные проблемы с кодировкой (не знаю, почему это стало происходить сейчас) с пакетом abab. Кажется, что в большинстве случаев он правильно кодируется, но иногда на внешнем интерфейсе кодируется неправильно. Потратил много времени на попытки отладки, но переключился на пакет base-64 в соответствии с рекомендациями, и он сразу заработал. Определенно, похоже, что до алгоритма base64 из abab.

Ответ 6

У меня есть код, общий для сервера и клиента, и мне нужна была реализация 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')
    }
};