[node.js] Node.js에서“btoa is not defined”오류 발생

내 node.js 응용 프로그램 npm install btoa-atob에서 클라이언트 측 자바 스크립트에 고유하지만 어떤 이유로 노드에 포함되지 않은 btoa () 및 atob () 함수를 사용할 수 있도록했습니다. 새 디렉토리는 node.modules 폴더에 나타 났으며 app.js와 함께 루트에 있습니다. 그런 다음 루트에있는 package.json 파일에서 btoa-atob를 종속성으로 추가했는지 확인했습니다.

그러나 어떤 이유로 든 여전히 작동하지 않습니다.

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

^ “SGVsbG8gV29ybGQh”를 콘솔에 출력해야하지만 대신 “btoa is not defined”오류가 발생합니다.

제대로 설치하지 않았습니까? 무엇을 간과 했습니까?



답변

‘btoa-atob’모듈은 프로그래밍 인터페이스를 내 보내지 않으며 명령 줄 유틸리티 만 제공합니다.

Base64로 변환해야하는 경우 버퍼를 사용하여 수행 할 수 있습니다.

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

역전 (복호하는 내용이 utf8 문자열이라고 가정) :

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

참고 : 노드 V4 이전에 사용 new Buffer보다는 Buffer.from.


답변

여기에 게시 된 솔루션은 ASCII가 아닌 문자로 작동하지 않습니다 (즉, Node.js와 브라우저간에 base64를 교환하려는 경우). 제대로 작동하려면 입력 텍스트를 ‘이진’으로 표시해야합니다.

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 패키지의 구현에서 얻었습니다 .


답변

내 팀은 React Native 및 PouchDB와 함께 Node를 사용할 때이 문제가 발생했습니다. 우리가 그것을 해결 한 방법은 다음과 같습니다.

NPM 설치 버퍼 :

$ npm install --save buffer

확인 Buffer, btoaatob전역으로로드됩니다

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


답변

위의 답변으로 인한 심이 작동했지만 데스크톱 브라우저의 구현 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를 위해서는 :

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


답변

나는이 코드는 서버와 클라이언트간에 공유 하고 내가 그 안에 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')
    }
};


답변

나는 이것이 노드 응용 프로그램에 대한 토론 지점이라는 것을 이해하지만 노드 서버에서 실행되는 범용 JavaScript 응용 프로그램에 관심 이 있기 때문에이 게시물에 도착한 방법은 보편적 / 동형 반응 응용 프로그램에 대해 조사했습니다. 건물과 패키지 abab가 나를 위해 일했습니다. 사실 그것은 Buffer 방법을 사용하는 대신 (유형 스크립트 문제가 있음) 작동하는 유일한 해결책이었습니다.

(이 패키지는에서 사용하며 jsdom, 패키지 에서 사용됩니다 window.)

내 요점으로 돌아 가기; 이를 기반으로, 아마도이 기능이 이미 언급 한 것과 같은 npm 패키지로 작성되었고 W3 사양을 기반으로 자체 알고리즘을 가지고 있다면 설치 및 사용할 수 있습니다abab 패키지를 수 있습니다. 인코딩에 따라 정확합니다.

편집

package와 함께 인코딩 (지금 시작하는 이유를 확실하지 않음)과 관련하여 오늘 이상한 문제가 발생했습니다 abab. 대부분의 경우 올바르게 인코딩하는 것처럼 보이지만 때로는 프런트 엔드에서 잘못 인코딩됩니다. 디버깅에 오랜 시간을 소비했지만 base-64권장대로 패키지 로 전환 했으며 곧바로 작동했습니다. 확실히의 base64 알고리즘에 해당하는 것 같습니다 abab.


답변

btoa () 또는 atob ()이없는 이전 버전의 노드 인 Atom 편집기의 ‘script’플러그인과 동일한 문제가 아니며 버퍼 데이터 유형을 지원하지 않습니다. 다음 코드는 트릭을 수행합니다.

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