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