클라이언트 측 Javascript의 Base64 인코딩 및 디코딩


답변:


214

Firefox, Chrome, Safari, Opera 및 IE10 +와 같은 일부 브라우저는 기본적으로 Base64를 처리 할 수 ​​있습니다. 이 Stackoverflow 질문을 살펴보십시오 . 사용 btoa()하고 atob()기능 합니다.

서버 측 JavaScript (노드)의 경우 Buffers를 사용 하여 디코딩 할 수 있습니다 .

크로스 브라우저 솔루션을 사용 하려는 경우 CryptoJS 와 같은 기존 라이브러리 또는 다음과 같은 코드가 있습니다.

http://ntt.cc/2008/01/19/base64-encoder-decoder-with-javascript.html

후자를 사용하면 크로스 브라우저 호환성을 위해 기능을 철저히 테스트해야합니다. 그리고 오류 가 이미보고되었습니다 .


1
이 방법을 사용하여 base64에서 SVG를 날짜 URI 체계로 인코딩했습니다. 놀랍게도 :이 함수는 모든 문자를 urlencode하므로 대상에서이 잘못된 XML을 얻습니다. % 3C % 3Fxml % 20version % 3D % 271.0 % 27 % 20 % 3F % 3E % 3Csvg % 20xmlns % 3D % 27http % ...
Dereckson

21
Node.js를 기본적 Base64로 작업을 수행 할 수 있습니다 new Buffer('Hello, world!').toString('base64'); new Buffer('SGVsbG8sIHdvcmxkIQ==', 'base64').toString('ascii'); (소스)
nyuszika7h

URL 안전을 원한다면?
anddero

1
노드 5+에서는 new Buffer(string)더 이상 사용되지 않는 Buffer.from을 사용하십시오. Buffer.from(jwt.split('.')[1], 'base64').toString()
Ray Foss

63

Gecko / WebKit 기반 브라우저 (Firefox, Chrome 및 Safari) 및 Opera에서 btoa ()atob ()을 사용할 수 있습니다 .

원래 답변 : JavaScript에서 문자열을 Base64로 인코딩하는 방법은 무엇입니까?


이것은 생명의 은인입니다. 매우 큰 base64 인코딩 문자열을 디코딩하기 위해 몇 가지 구현을 사용했으며 결과는 항상 잘못되었습니다. atob ()은 훌륭하게 작동합니다!
b2238488

15
작은 nitpick : Opera는 Gecko 또는 Webkit을 기반으로하지 않으며 Presto라는 자체 렌더링 엔진을 사용합니다.
피터 올슨

와, 고마워 이 브라우저에 기본 base64 인코더가 있다는 것을 몰랐습니다!
Rob Porter

5
@PeterOlson 더 이상은 아닙니다 :)
Mustafa

1
나는 이것이 오래된 게시물이라는 것을 알고 있지만 @ b2238488의 문제에 대해 각 토큰의 길이가 4의 배수가되도록 base64 문자열을 분할하고 별도로 디코딩 할 수 있습니다. 결과는 전체 문자열을 한 번에 디코딩하는 것과 같습니다.
nyuszika7 시간

56

Internet Explorer 10 이상

// Define the string
var string = 'Hello World!';

// Encode the String
var encodedString = btoa(string);
console.log(encodedString); // Outputs: "SGVsbG8gV29ybGQh"

// Decode the String
var decodedString = atob(encodedString);
console.log(decodedString); // Outputs: "Hello World!"

크로스 브라우저

AMD, CommonJS, Nodejs 및 브라우저 용 UTF-8 및 Base64 Javascript 인코딩 및 디코딩 라이브러리 / 모듈을 다시 작성하고 모듈화했습니다. 크로스 브라우저 호환


Node.js로

Node.js에서 일반 텍스트를 base64로 인코딩하는 방법은 다음과 같습니다.

//Buffer() requires a number, array or string as the first parameter, and an optional encoding type as the second parameter. 
// Default is utf8, possible encoding types are ascii, utf8, ucs2, base64, binary, and hex
var b = new Buffer('JavaScript');
// If we don't use toString(), JavaScript assumes we want to convert the object to utf8.
// We can make it convert to other formats by passing the encoding type to toString().
var s = b.toString('base64');

base64로 인코딩 된 문자열을 디코딩하는 방법은 다음과 같습니다.

var b = new Buffer('SmF2YVNjcmlwdA==', 'base64')
var s = b.toString();

Dojo.js로

dojox.encoding.base64를 사용하여 바이트 배열을 인코딩하려면 다음을 수행하십시오.

var str = dojox.encoding.base64.encode(myByteArray);

base64로 인코딩 된 문자열을 디코딩하려면

var bytes = dojox.encoding.base64.decode(str)

바우처 설치 앵귤러베이스 64

<script src="bower_components/angular-base64/angular-base64.js"></script>

angular
    .module('myApp', ['base64'])
    .controller('myController', [

    '$base64', '$scope', 
    function($base64, $scope) {
    
        $scope.encoded = $base64.encode('a string');
        $scope.decoded = $base64.decode('YSBzdHJpbmc=');
}]);

그러나 어떻게?

base64가 일반적으로 인코딩되고 특히 JavaScript에서 인코딩되는 방법에 대해 더 배우고 싶다면이 기사를 추천합니다 : JavaScript의 컴퓨터 과학 : Base64 인코딩


1
참고 : 크로스 브라우저 버전에 성가신 누출을 가지고 c2가능성 c1c3그것이 작동하지 않습니다 그래서 "use strict"위에 정의 된 바와 같다.
Campbeln

41

스나이퍼 포스트의 강화 버전입니다. 캐리지 리턴이없는 잘 구성된 base64 문자열을 가정합니다. 이 버전은 두 개의 루프를 제거하고 &0xffYaroslav 의 수정 사항을 추가하며 후행 null과 코드 골프를 제거합니다.

decodeBase64 = function(s) {
    var e={},i,b=0,c,x,l=0,a,r='',w=String.fromCharCode,L=s.length;
    var A="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    for(i=0;i<64;i++){e[A.charAt(i)]=i;}
    for(x=0;x<L;x++){
        c=e[s.charAt(x)];b=(b<<6)+c;l+=6;
        while(l>=8){((a=(b>>>(l-=8))&0xff)||(x<(L-2)))&&(r+=w(a));}
    }
    return r;
};

5
더 적은 바이트; DdecodeBase64=function(f){var g={},b=65,d=0,a,c=0,h,e="",k=String.fromCharCode,l=f.length;for(a="";91>b;)a+=k(b++);a+=a.toLowerCase()+"0123456789+/";for(b=0;64>b;b++)g[a.charAt(b)]=b;for(a=0;a<l;a++)for(b=g[f.charAt(a)],d=(d<<6)+b,c+=6;8<=c;)((h=d>>>(c-=8)&255)||a<l-2)&&(e+=k(h));return e};
데르 Hochstapler

예. 그러나 ASCII에서만 작동합니다. 예를 들어 Cyr 문자는 엉망입니다.
Martin Kovachev

@ MartinKovachev Cyr 문자와 해당 base64 인코딩이있는 예제 텍스트로 새로운 주석을 게시 할 수 있습니까? 어쩌면 우리는 수용하기 위해 코드를 고칠 수 있습니다.
broc.seib

여기 : 그런 것 : тестова фраза
Martin Kovachev

2
@OliverSalzburg 더 적은 코드 테이블 생성 :) :var g={},k=String.fromCharCode,i;for(i=0;i<64;)g[k(i>61?(i&1)*4|43:i+[65,71,-4][i/26&3])]=i++;
Mike

34

페일 세이프가없는 짧고 빠른 Base64 JavaScript 디코딩 기능 :

function decode_base64 (s)
{
    var e = {}, i, k, v = [], r = '', w = String.fromCharCode;
    var n = [[65, 91], [97, 123], [48, 58], [43, 44], [47, 48]];

    for (z in n)
    {
        for (i = n[z][0]; i < n[z][1]; i++)
        {
            v.push(w(i));
        }
    }
    for (i = 0; i < 64; i++)
    {
        e[v[i]] = i;
    }

    for (i = 0; i < s.length; i+=72)
    {
        var b = 0, c, x, l = 0, o = s.substring(i, i+72);
        for (x = 0; x < o.length; x++)
        {
            c = e[o.charAt(x)];
            b = (b << 6) + c;
            l += 6;
            while (l >= 8)
            {
                r += w((b >>> (l -= 8)) % 256);
            }
         }
    }
    return r;
}

6
오페라 11.62는 '% 256'부분에 문제가있는 것 같습니다. '& 0xff'로 바꾸면 작동합니다.
Yaroslav Stavnichiy

Tyk 가상 엔드 포인트 자바 스크립트 코드에 '\ x00'부분에 문제가있는 것 같습니다. r = r.replace (/ \ x00 / g, '')로
바꾸면


11

php.js의 프로젝트는 PHP의 기능 중 많은 자바 스크립트 구현이 있습니다. base64_encode그리고 base64_decode포함되어 있습니다.


php.js는 모든 악의 화신이며 지옥의 자체 계층에 속합니다. 전염병처럼 피하십시오. (추가 정보 : softwareengineering.stackexchange.com/questions/126671/… )
Coreus

해당 링크에서 @Coreus와 같은 담요 어설 션을 많이 지원하지는 않습니다. 신중하게 또는 시작점으로 사용하면 PHP에서 이미 수행하는 방법에 대해 JS에서 동등한 논리를 파악할 수 있습니다.
ceejayoz

9

누군가 코드 골프라고 했습니까? =)

다음은 시대를 따라 잡는 동안 핸디캡을 개선하려는 나의 시도입니다. 귀하의 편의를 위해 제공됩니다.

function decode_base64(s) {
  var b=l=0, r='',
  m='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
  s.split('').forEach(function (v) {
    b=(b<<6)+m.indexOf(v); l+=6;
    if (l>=8) r+=String.fromCharCode((b>>>(l-=8))&0xff);
  });
  return r;
}

실제로 실제로 수행 한 것은 비동기 구현이었고 놀랍게도 forEachJQuery의 $([]).each메소드 구현과는 대조적으로 매우 동 기적 인 것으로 나타났습니다 .

이러한 미친 개념을 염두에두면 0 지연 window.setTimeout이 base64 디코드를 비동기 적으로 실행하고 완료되면 콜백 함수를 결과와 함께 실행합니다.

function decode_base64_async(s, cb) {
  setTimeout(function () { cb(decode_base64(s)); }, 0);
}

@Toothbrush는 "배열과 같은 문자열 색인화"를 제안하고를 제거합니다 split. 이 루틴은 정말 이상하게 보이며 그것이 얼마나 호환되는지 확실하지 않지만 다른 버디를 때 리므로 그렇게하십시오.

function decode_base64(s) {
  var b=l=0, r='',
  m='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
  [].forEach.call(s, function (v) {
    b=(b<<6)+m.indexOf(v); l+=6;
    if (l>=8) r+=String.fromCharCode((b>>>(l-=8))&0xff);
  });
  return r;
}

배열로 JavaScript 문자열에 대한 자세한 정보를 찾으려고하는 동안 /./g정규식을 사용하여 문자열을 단계별로 사용 하여이 팁을 우연히 발견했습니다 . 이렇게하면 문자열을 제자리에 놓고 반환 변수를 유지할 필요가 없어 코드 크기가 훨씬 줄어 듭니다.

function decode_base64(s) {
  var b=l=0,
  m='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
  return s.replace(/./g, function (v) {
    b=(b<<6)+m.indexOf(v); l+=6;
    return l<8?'':String.fromCharCode((b>>>(l-=8))&0xff);
  });
}

그러나 좀 더 전통적인 것을 찾고 있다면 아마도 다음과 같은 것이 당신의 취향에 더 가깝습니다.

function decode_base64(s) {
  var b=l=0, r='', s=s.split(''), i,
  m='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
  for (i in s) {
    b=(b<<6)+m.indexOf(s[i]); l+=6;
    if (l>=8) r+=String.fromCharCode((b>>>(l-=8))&0xff);
  }
  return r;
}

나는 후행 null 문제가 없었 으므로이 문제는 파로 남아 있기 위해 제거되었지만 원하는 경우 a trim()또는 a로 쉽게 해결할 수 있습니다 trimRight().

즉.

return r.trimRight();

노트 :

결과는 ASCII 바이트 문자열입니다. 유니 코드가 필요한 경우 가장 쉬운 것은 escape바이트 문자열입니다. 그런 다음 decodeURIComponent유니 코드 문자열을 생성하기 위해 함께 디코딩 할 수 있습니다 .

function decode_base64_usc(s) {      
  return decodeURIComponent(escape(decode_base64(s)));
}

이후 escape우리가 직접 할 필요없이 지원 유니 코드에 대한 우리의 기능을 변경할 수있는 사용되지되고 escape또는 String.fromCharCode우리가 생산할 수있는 %URI 디코딩을위한 준비가 탈출 문자열입니다.

function decode_base64(s) {
  var b=l=0,
  m='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
  return decodeURIComponent(s.replace(/./g, function (v) {
    b=(b<<6)+m.indexOf(v); l+=6;
    return l<8?'':'%'+(0x100+((b>>>(l-=8))&0xff)).toString(16).slice(-2);
  }));
}

조이!


3
split배열과 같은 JavaScript 문자열을 인덱싱 할 수 있으므로 문자열 을 사용할 필요가 없습니다 . s.split('').forEach(function ...로 대체 할 수 있습니다 [].forEach.call(s, function .... 문자열을 나눌 필요가 없기 때문에 훨씬 빠릅니다.
칫솔

"보다 전통적인"것이 나를 위해 완전히 깨졌습니다. 원본 전체에 뿌려진 원본 텍스트로 왜곡 된 혼란을 일으켰습니다. Chrome에서.
Steve Bennett

@Steve Bennett 크롬의 모든 변형을 테스트했습니다 ... 작동합니다. 실패한 예제 base64 문자열을 제공 할 수 있습니까?
nickl-

3 년 후에? 하아. 나는 이것이 무엇을 필요로했는지조차 기억하지 못한다.
Steve Bennett

6

phpjs.org에서 Javascript 루틴을 시도했으며 잘 작동했습니다.

내가 처음 Ranhiru Cooray에 의해 선택된 대답에 제안 된 루틴을 시도 - http://ntt.cc/2008/01/19/base64-encoder-decoder-with-javascript.html

나는 그들이 모든 상황에서 작동하지 않는다는 것을 발견했다. 이 루틴이 실패하고 GitHub에 게시 한 테스트 사례를 작성했습니다.

https://github.com/scottcarter/base64_javascript_test_data.git

또한 ntt.cc의 블로그 게시물에 작성자에게 알리기 위해 의견을 게시했습니다 (조정 대기 중-기사가 오래되어서 의견이 게시 될지 확실하지 않음).


1

모범 사례와 패턴을 사용하여 JavaScript로 구현 된 표준 및 보안 암호화 알고리즘을위한 가장 인기있는 라이브러리 인 CryptoJS 의 bas64 인코딩 / 디코딩 방법을 사용하고 싶습니다 .


1

Node.js에서 간단한 방법으로 할 수 있습니다

var base64 = 'SGVsbG8gV29ybGQ='
var base64_decode = new Buffer(base64, 'base64').toString('ascii');

console.log(base64_decode); // "Hello World"

0

atob메소드 가없는 JavaScript 프레임 워크의 경우 외부 라이브러리를 가져 오지 않으려는 경우이를 수행하는 짧은 기능입니다.

Base64로 인코딩 된 값이 포함 된 문자열을 가져 와서 디코딩 된 바이트 배열을 반환합니다 (바이트 배열은 각 숫자가 0에서 255 사이의 정수인 숫자의 배열로 나타납니다).

function fromBase64String(str) {
    var alpha = 
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    var value = [];
    var index = 0;
    var destIndex  = 0;
    var padding = false;
    while (true) {

        var first  = getNextChr(str, index, padding, alpha);
        var second = getNextChr(str, first .nextIndex, first .padding, alpha);
        var third  = getNextChr(str, second.nextIndex, second.padding, alpha);
        var fourth = getNextChr(str, third .nextIndex, third .padding, alpha);

        index = fourth.nextIndex;
        padding = fourth.padding;

        // ffffffss sssstttt ttffffff
        var base64_first  = first.code  == null ? 0 : first.code;
        var base64_second = second.code == null ? 0 : second.code;
        var base64_third  = third.code  == null ? 0 : third.code;
        var base64_fourth = fourth.code == null ? 0 : fourth.code;

        var a = (( base64_first << 2) & 0xFC ) | ((base64_second>>4) & 0x03);
        var b = (( base64_second<< 4) & 0xF0 ) | ((base64_third >>2) & 0x0F);
        var c = (( base64_third << 6) & 0xC0 ) | ((base64_fourth>>0) & 0x3F);

        value [destIndex++] = a;
        if (!third.padding) {
            value [destIndex++] = b;
        } else {
            break;
        }
        if (!fourth.padding) {
            value [destIndex++] = c;
        } else {
            break;
        }
        if (index >= str.length) {
            break;
        }
    }
    return value;
}

function getNextChr(str, index, equalSignReceived, alpha) {
    var chr = null;
    var code = 0;
    var padding = equalSignReceived;
    while (index < str.length) {
        chr = str.charAt(index);
        if (chr == " " || chr == "\r" || chr == "\n" || chr == "\t") {
            index++;
            continue;
        }
        if (chr == "=") {
            padding = true;
        } else {
            if (equalSignReceived) {
                throw new Error("Invalid Base64 Endcoding character \"" 
                    + chr + "\" with code " + str.charCodeAt(index) 
                    + " on position " + index 
                    + " received afer an equal sign (=) padding "
                    + "character has already been received. "
                    + "The equal sign padding character is the only "
                    + "possible padding character at the end.");
            }
            code = alpha.indexOf(chr);
            if (code == -1) {
                throw new Error("Invalid Base64 Encoding character \"" 
                    + chr + "\" with code " + str.charCodeAt(index) 
                    + " on position " + index + ".");
            }
        }
        break;
    }
    return { character: chr, code: code, padding: padding, nextIndex: ++index};
}

사용 된 자원 : RFC-4648 섹션 4

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.