クライアント側の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
このメソッドを使用して、Date URIスキームでbase64でSVGをエンコードしました。驚き:この関数はすべての文字を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 2014

そして、私がそれを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 2011

15
小さなnitpick:OperaはGeckoやWebkitをベースにしておらず、Prestoと呼ばれる独自のレンダリングエンジンを使用しています。
Peter Olson

わあ、ありがとう。これらのブラウザーにネイティブのbase64エンコーダーがあることを知りませんでした!
Rob Porter、

5
@PeterOlsonもういません:)
Mustafa

1
これは古い投稿ですが、@ b2238488の懸念については、base64文字列を分割して、各トークンの長さが4の倍数になるようにして、個別にデコードすることができます。結果は、文字列全体を一度にデコードした場合と同じになります。
nyuszika7h 2013

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)

bower install angular-base64

<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
FYI:クロスブラウザのバージョンが持ついくつかの厄介なリークがありc2、おそらくc1c3、それは動作しませんので、"use strict"上記定義した通りです。
Campbeln、2015年

41

こちらはスナイパーの投稿の引き締めバージョンです。改行なしの整形式のbase64文字列を想定しています。このバージョンでは、いくつかのループが削除され、&0xffYaroslavからの修正が追加され、末尾のヌルが削除され、さらにコードのゴルフが少し追加されています。

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};
Der Hochstapler

そうですが、ASCIIでのみ機能します。たとえば、Cyrキャラクターが壊されます。
Martin Kovachev 2015

@MartinKovachevは、Cyr文字と対応するbase64エンコードを使用したテキスト例を含む新しいコメントを投稿できますか?たぶん、コードを修正して対応できます。
broc.seib 2015

ここに:そのような何か:тестовафраза
マーティン・コバチェブ

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
Opera 11.62は '%256'の部分に問題があるようです。'&0xff'で置き換えると機能します。
Yaroslav Stavnichiy

Tyk仮想エンドポイントのJavaScriptコードに「\ x00」の部分で問題があるようです。それをr = r.replace(/ \ x00 / g、 '')で置き換えると機能します
Panupong Kongarn


11

php.jsのプロジェクトはPHPの機能の多くのJavaScriptの実装を持っています。base64_encodebase64_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;
}

私が実際に求めていたのは非同期実装であり、驚いたことに forEach、JQueryの$([]).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の問題はなかったので、これは標準以下にとどまるために削除されましたが、簡単に解決する必要があります trim()またはatrimRight()、問題が発生し場合できます。

すなわち。

return r.trimRight();

注意:

結果はASCIIバイト文字列です。Unicodeが必要な場合、最も簡単なのはescapeバイト文字列で、これをデコードしdecodeURIComponentてUnicode文字列を生成できます。

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

nJoy!


3
split配列のようにJavaScript文字列にインデックスを付けることができるため、文字列を使用する必要はありません。s.split('').forEach(function ...で置き換えることができます[].forEach.call(s, function ...。文字列を分割する必要がないため、はるかに高速になります。
歯ブラシ2014

「より伝統的な」ものは私にとって完全に壊れていました-元のテキストの痕跡が散りばめられて文字化けした混乱を生み出しました。Chrome。
Steve Bennett

@Steve Bennett私はすべてのバリアントをクロムでテストしました...それは動作します。失敗するbase64文字列の例を提供できますか?
nickl-

3年後?ハ。何のためにこれを必要としていたのかさえ覚えていません。
スティーブベネット

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

私はむしろからbas64エンコード/デコード方法使用したいCryptoJS、ベストプラクティスやパターンを使用してJavaScriptで実装標準とセキュアな暗号化アルゴリズムのための最も人気のあるライブラリを。


1

Node.jsでは、簡単な方法でそれを行うことができます

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

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

0

ないJavaScriptフレームワークの場合 atobメソッド、外部ライブラリをインポートしたくない場合の場合、これはそれを行う短い関数です。

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.