Node.js “btoa tanımlanmadı” hatası veriyor


231

Node.js uygulamamda npm install btoa-atob, istemci tarafı javascript'te yerel olan btoa () ve atob () işlevlerini kullanabilmem için bir yöntem yaptım, ancak bir nedenden dolayı düğüme dahil edilmedi. Yeni dizin, app.js'nin yanında kök olan node_modules klasörümde ortaya çıktı. Sonra btoa-atob kök olan benim package.json dosyasında bir bağımlılık olarak eklemek emin oldum.

Ancak, bazı nedenlerden dolayı, hala çalışmaz.

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

^ konsola "SGVsbG8gV29ybGQh" çıktı gerekir, ancak bunun yerine "btoa tanımlanmadı" hatası alıyorum.

Kurulumu düzgün yapmadım mı? Neyi gözden kaçırdım?

Yanıtlar:


540

'Btoa-atob' modülü programlı bir arayüzü dışa aktarmaz, sadece komut satırı yardımcı programları sağlar.

Base64'e dönüştürmeniz gerekiyorsa, Arabellek kullanarak bunu yapabilirsiniz:

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

Ters (kodunu çözdüğünüz içeriğin bir utf8 dizesi olduğu varsayılarak):

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

Not: Düğüm v4'ten önce kullanmak new Bufferyerine , kullanın Buffer.from.


57

Burada yayınlanan çözümler ascii olmayan karakterlerde çalışmaz (örneğin, Node.js ile bir tarayıcı arasında base64 değiştirmeyi planlıyorsanız). Çalışması için giriş metnini 'ikili' olarak işaretlemeniz gerekir.

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

Bu sana verir SOlsbPMgd/NybGQhIQ==. atob('SOlsbPMgd/NybGQhIQ==')Bir tarayıcıda yaparsanız , doğru şekilde çözecektir. Ayrıca Node.js'de de şu şekilde yapılır:

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

Eğer "ikili kısmı" yapmazsanız, özel karakterleri yanlış çözeceksiniz.

Ben btoa npm paketinin uygulanmasından aldım :


1
teşekkürler, değişen karakterlerle deliriyordum.
Matthew James Briggs

1
Teşekkürler Ivan, ben bu saatlerce olurdu ... cevap kabul edilen olmalı!
Pawel

Iván Alegre 'İkili' kodlamayı kullanmayın. Bunu yaparsanız Buffer.from('Hélló wórld!!').toString('base64')- SOlsbPMgd/NybGQhIQ==hangi düzgün ASCII olmayan dize dönüştürülebilir verebilir .
TotalAMD

1
@TotalAMD, No64.js'den tarayıcı veya viceversa'ya base64 alışverişi yapmayacak
Iván Alegre

3
Base64'te kodlamayı karşılaştırıyorsunuz ve aynı platformda kodunu çözüyorsunuz. Chrome'dan Chrome'a ​​ve Düğümden Düğüme. Düğüm 10'da ikili olmadan kodlarsanız, verir SMOpbGzDsyB3w7NybGQhIQ==. Bunu bir tarayıcıda çözerseniz, size verir Hélló wórld!!. İkili, platformlar arası uyumluluğu sağlamak için mükemmeldir.
Iván Alegre

22

React Native ve PouchDB ile Düğüm kullanırken ekibim bu problemle karşılaştı. İşte böyle çözdük ...

NPM kurulum tamponu:

$ npm install --save buffer

Emin olun Buffer, btoave atobbir globaller olarak yüklenir:

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

2
Kodunuzdaki new Buffer () komutu, yeni düğüm sürümlerinde şu hatayı verir: [DEP0005] DeprecationWarning: Buffer (), güvenlik ve kullanılabilirlik sorunları nedeniyle kullanımdan kaldırıldı. Lütfen bunun yerine Buffer.alloc (), Buffer.allocUnsafe () veya Buffer.from () yöntemlerini kullanın.
Rodrigo De Almeida Siqueira

8

Ben yanıtlarından şim çalıştı yukarıda rağmen, bunlar masaüstü tarayıcıların uygulamaların davranışını eşleşmedi bulundu btoa()ve 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])));

Anlaşıldığı üzere, Bufferörnekler varsayılan olarak UTF-8'de kodlanmış dizeleri temsil eder / yorumlar . Bunun aksine, masaüstü Chrome'da, btoa()bir istisna oluşturacağından latin1 aralığının dışında karakterler içeren bir dize bile giremezsiniz :Uncaught DOMException: Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range.

Bu nedenle, açıkça ayarlamanız gerekir kodlama türünü için latin1masaüstü Chrome kodlama türünü eşleştirmek için şim sizin node.js için sırayla:

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])));

v0.12.2 düğümünde bir Buffer.from işlevi yok
Zibri

@ Zibri Düğümü v0.12.2 eski ve iki yıl önce ömrünün sonuna ulaştı . Buffer.from()olduğu önerilen yolu (bağlantı alternatifleri netleştirecek rağmen güvenlik nedeniyle Tampon API kullanmayı Buffer.from()Düğüm v0.12.2 için de geçerli olabilir).
Jamie Birch

Bunu anlıyorum, ancak gömülü bir cihazda bu sürüme sahibim.
Zibri

Kodumu eski bir düğüm uygulaması olan github.com/rgbkrk/atom-script komut dosyasını kullanarak Atom'da çalıştırıyorum . Başka bir deyişle, buffer.from () ile baş edemese de, btoa için de bir uygulamaya ihtiyacı vardır.
19'da Karides

4

Sunucu ve istemci arasında paylaşılan bir kod var ve içinde btoa bir uygulama gerekli. Gibi bir şey yapmayı denedim:

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

ancak Sunucu şunlarla ezilecektir:

ReferenceError: btoa tanımlanmamış

while Bufferistemcide tanımlı değil.

Window.btoa'yı kontrol edemedim (bu paylaşılan bir kod, hatırladın mı?)

Bu uygulama ile sonuçlandım:

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

1

Bunun bir düğüm uygulaması için bir tartışma noktası olduğunu anlıyorum, ancak bir düğüm sunucusunda çalışan evrensel JavaScript uygulamalarının yararına , bu gönderiye nasıl geldiğimi, bunu bir evrensel / izomorfik reaksiyon uygulaması için araştırıyorum ve paket ababbenim için çalıştı. Aslında, bu tampon yöntemini kullanmak yerine, işe yarayan bulabildiğim tek çözümdü (daktilo sorunları vardı).

(Bu paket tarafından jsdomkullanılır ve bu windowpaket tarafından kullanılır .)

Benim açımdan döneceğim; buna dayanarak, belki de bu işlevsellik daha önce bahsettiğiniz gibi bir npm paketi olarak yazıldıysa ve W3 spesifikasyonuna dayalı kendi algoritması ababvarsa, kendi işlevinizi yazıp yazamayacağınız yerine paketi kurabilir ve kullanabilirsiniz. kodlamaya dayalı olarak doğru.

--- DÜZENLE ---

Bugün kod ile (şimdi neden başladığından emin değilim) paketle garip sorunlar yaşamaya başladım abab. Çoğu zaman doğru kodlanmış gibi görünür, ancak bazen ön uçta yanlış kodlar. Hata ayıklamaya çalışırken uzun zaman geçirdim, ancak base-64önerildiği gibi pakete geçti ve hemen çalıştı. Kesinlikle aşağı base64 algoritması gibi görünüyordu abab.


1

Düğümün eski bir sürümü olan, btoa () veya atob () içermeyen ve buffer veri tipini desteklemeyen Atom editöründeki 'script' eklentisi ile aynı problem. Aşağıdaki kod hile yapar:

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


Bu işe yarıyor teşekkürler. Benim durumumda, atob'ı desteklemeyen ChakraEngine kullanıyorum.
Su


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

0

İşte base64 kodlaması için özlü bir evrensel çözüm:

const nodeBtoa = (b) => Buffer.from(b).toString('base64');
export const base64encode = typeof btoa !== 'undefined' ? btoa : nodeBtoa;
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.