JavaScript プログラミング講座

 

Base64 とは?

 


■ Base64 とは?


Base64 は、65 種類の文字を使って、バイナリデータを、文字列で表現する事ができます。
 
テキストフォーマットの一種です。
 
基本的なエンコード部分には、英数字『 a-zA-Z0-9 』と加算記号『 + 』、スラッシュ『 / 』の、合計 64 文字を使用します。
 
終端で発生する、余りを埋めるのに、等号『 = 』を使用します。
 
Base64 のサイズは、バイナリのサイズと比較すると、約 4/3 倍に増えます
 
Base64 のサイズは、必ず 4 の倍数となります。
 
Base64 は、メールの添付ファイルなどで利用されています。
 


 

Base64 のフォーマットについて

 
 


■ Base64 変換テーブル

 
番号 文字 番号 文字 番号 文字
0 "A" (0x41) 26 "a" (0x61) 52 "0" (0x30)
1 "B" (0x42) 27 "b" (0x62) 53 "1" (0x31)
2 "C" (0x43) 28 "c" (0x63) 54 "2" (0x32)
3 "D" (0x44) 29 "d" (0x64) 55 "3" (0x33)
4 "E" (0x45) 30 "e" (0x65) 56 "4" (0x34)
5 "F" (0x46) 31 "f" (0x66) 57 "5" (0x35)
6 "G" (0x47) 32 "g" (0x67) 58 "6" (0x36)
7 "H" (0x48) 33 "h" (0x68) 59 "7" (0x37)
8 "I" (0x49) 34 "i" (0x69) 60 "8" (0x38)
9 "J" (0x4a) 35 "j" (0x6a) 61 "9" (0x39)
10 "K" (0x4b) 36 "k" (0x6b) 62 "+" (0x2b)
11 "L" (0x4c) 37 "l" (0x6c) 63 "/" (0x2f)
12 "M" (0x4d) 38 "m" (0x6d)
13 "N" (0x4e) 39 "n" (0x6e)
14 "O" (0x4f) 40 "o" (0x6f)
15 "P" (0x50) 41 "p" (0x70)
16 "Q" (0x51) 42 "q" (0x71)
17 "R" (0x52) 43 "r" (0x72)
18 "S" (0x53) 44 "s" (0x73)
19 "T" (0x54) 45 "t" (0x74)
20 "U" (0x55) 46 "u" (0x75)
21 "V" (0x56) 47 "v" (0x76)
22 "W" (0x57) 48 "w" (0x77)
23 "X" (0x58) 49 "x" (0x78)
24 "Y" (0x59) 50 "y" (0x79)
25 "Z" (0x5a) 51 "z" (0x7a)
 

■バイナリから Base64 にエンコードする

 
■ Base64 の総サイズを計算する
 
バイナリのサイズを 3 で割り、小数を切り上げます。
 
さらに 4 を掛けた結果が、Base64 の総サイズとなります。
 
■バイナリから Base64 にエンコードする
 
バイナリの 0 番目から順番に 6 bit ずつデータを取り出します。
 
得られた値は、変換テーブルを使って文字に変換します。
 
バイナリ 3 バイトごとに、4 文字分のテキストが発生する事になります。
 
111111 | 112222 | 222233 | 333333
 
バイナリが最後尾に到達した場合、残りは 0 で埋めます。
 
最後に、バイナリの総サイズを 3 で割ります。
 
余りが 1 だった場合、Base64 の最後尾に、等号『 = 』を 2 つ追加します。
 
余りが 2 だった場合、Base64 の最後尾に、等号『 = 』を 1 つ追加します。
 

■ Base64 からバイナリにデコードする

 
■バイナリの総サイズを計算する
 
まず、Base64 のサイズを 4 で割ります。
 
もし余りが発生する場合、Base64 は異常なデータです。
 
次に、Base64 の最後尾に、等号『 = 』が連続して存在するか調べます。
 
最大で 2 個存在します。
 
バイナリの総サイズは、以下の通りです。
 
((Base64 のサイズ) / 4 * 3) - (等号の数)
 
■等号『 = 』の省略にも対応する場合
 
最後尾の等号『 = 』を省略できる変形仕様も存在します。
 
modified UTF-7 の modified Base64 など
 
まず、Base64 のサイズを 4 で割った余りを求めます。
 
余りが 0 である場合、最初の方法で計算を試みます。
 
余りが 1 である場合、Base64 は異常データです。
 
余りが 2 である場合、最後尾の "==" が省略されているとみなします。
 
余りが 3 である場合、最後尾の "=" が省略されているとみなします。
 
バイナリの総サイズは、以下の通りです。
 
Math.ceil((Base64 のサイズ) / 4) * 3 - (省略された等号の数)
 
■ Base64 からバイナリにデコードする
 
Base64 の 0 番目から順番に文字を取り出します。
 
得られた文字は、変換テーブルを使って、6 bit の値に変換します。
 
バイナリを 0 番目から順番に 6 bit ずつ、上位から埋めていきます。
 
Base64 の 4 文字ごとに、3 バイトのバイナリが発生する事になります
 
11111122 | 22223333 | 33444444
 
バイナリが最後尾まで埋まった時点で完了です。
 
Base64 側は、等号『 = 』分が余ります。
 


 

Base64 と「バイナリデータ文字列」の相互変換

 
 


■「バイナリデータの文字列」について

 
■バイナリデータの文字列(String of binary data)とは?
 
0 ~ 255 までの文字コードのみで構成されている文字列です。
 
1文字で1バイトを表現します。
 
文字列の途中に、『 NUL (0x00) 』などの制御文字の混入が可能な、ECMAScript ならではの文字列となります。
 
■歴史について
 
JavaScript でバイナリを取り扱う仕組みが無かった時代 (NN4) に生まれた API ですが、HTML5 にて標準化されました。
 
HTML5 世代では、ArrayBuffer クラスを使って、バイナリを取り扱います。
 

■「バイナリデータの文字列」から「Base64 文字列」にエンコード

 
■バイナリデータの文字列から、Base64 文字列に変換する
 
btoa() メソッドを使用します。
 
「Binary (String)」 to 「ASCII (Base64)」 の略のようです。
 
このメソッドは、Internet Explorer 9 以前では未対応です。
 
Window.btoa( "バイナリデータの文字列" ) :String
第01引数 String0 ~ 255 までの文字コードのみで構成された、バイナリデータの文字列を指定する。違反している場合、例外エラーが発生する。
戻り値 StringBase64 文字列が得られる。
 
■第01引数(バイナリデータの文字列)
 
引数に、0 ~ 255 までの文字コードのみで構成されている文字列を指定します。
 
違反している場合、例外エラーが発生します。
 
数値を指定して、任意の1文字を得るには、String.fromCharCode() メソッドを使用します。
 
■使用例
 
バイナリデータの文字列から Base64 文字列に変換する

// ------------------------------------------------------------
// 配列を用意する
// ------------------------------------------------------------
var ary = [0x01,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9a,0xab,0xbc,0xcd,0xde,0xef];

// ------------------------------------------------------------
// 「バイナリデータの文字列」を作成する
// ------------------------------------------------------------
var string_of_binary = "";
var i;
var num = ary.length;
for(i=0;i < num;i++){
	string_of_binary += String.fromCharCode(ary[i]);
}

// ------------------------------------------------------------
// 「バイナリデータの文字列」から「Base64」に変換する
// ------------------------------------------------------------
var base64 = btoa(string_of_binary);

// 出力テスト
console.log(base64); // "ARIjNEVWZ3iJmqu8zd7v"
 
■ btoa() の代替関数
 
Internet Explorer 6 でも動作します。
 
バイナリデータの文字列から Base64 文字列に変換する関数

// ------------------------------------------------------------
// バイナリデータの文字列から Base64 文字列に変換する関数 (同期実行)
// ------------------------------------------------------------
function Base64_From_StringOfBinaryData(binary){
	var dic = [
		'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
		'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
		'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
		'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
	];
	var base64 = [];
	var num = binary.length;
	var n = 0;
	var b = 0;

	var i = 0;
	while(i < num){
		b = binary.charCodeAt(i);
		if(b > 0xff) return null;
		base64.push(dic[(b >> 2)]);
		n = (b & 0x03) << 4;
		i ++;
		if(i >= num) break;

		b = binary.charCodeAt(i);
		if(b > 0xff) return null;
		base64.push(dic[n | (b >> 4)]);
		n = (b & 0x0f) << 2;
		i ++;
		if(i >= num) break;

		b = binary.charCodeAt(i);
		if(b > 0xff) return null;
		base64.push(dic[n | (b >> 6)]);
		base64.push(dic[(b & 0x3f)]);
		i ++;
	}

	var m = num % 3;
	if(m){
		base64.push(dic[n]);
	}
	if(m == 1){
		base64.push("==");
	}else if(m == 2){
		base64.push("=");
	}
	return base64.join("");
}

// ------------------------------------------------------------
// バイナリデータの文字列から Base64 文字列に変換する関数 (非同期実行)
// ------------------------------------------------------------
function Base64_From_StringOfBinaryData_Async(binary,callback,increment){
	var dic = [
		'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
		'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
		'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
		'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
	];
	var base64 = [];
	var num = binary.length;
	var n = 0;
	var b = 0;

	if(increment === undefined){
		increment = 10240;
	}

	var i = 0;
	var j = 0;
	function f(){
		while(i < num){
			b = binary.charCodeAt(i);
			if(b > 0xff){ callback(null); return; }
			base64.push(dic[(b >> 2)]);
			n = (b & 0x03) << 4;
			i ++;
			if(i >= num) break;

			b = binary.charCodeAt(i);
			if(b > 0xff){ callback(null); return; }
			base64.push(dic[n | (b >> 4)]);
			n = (b & 0x0f) << 2;
			i ++;
			if(i >= num) break;

			b = binary.charCodeAt(i);
			if(b > 0xff){ callback(null); return; }
			base64.push(dic[n | (b >> 6)]);
			base64.push(dic[(b & 0x3f)]);
			i ++;

			j += 3;
			if(j > increment){
				j = 0;
				setTimeout(f,1);
				return;
			}
		}

		var m = num % 3;
		if(m){
			base64.push(dic[n]);
		}
		if(m == 1){
			base64.push("==");
		}else if(m == 2){
			base64.push("=");
		}
		callback(base64.join(""));
	}

	setTimeout(f,1);
}
 
使用例

// ------------------------------------------------------------
// 配列を用意する
// ------------------------------------------------------------
var ary = [0x01,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9a,0xab,0xbc,0xcd,0xde,0xef];

// ------------------------------------------------------------
// 「バイナリデータの文字列」を作成する
// ------------------------------------------------------------
var string_of_binary = "";
var i;
var num = ary.length;
for(i=0;i < num;i++){
	string_of_binary += String.fromCharCode(ary[i]);
}

// ------------------------------------------------------------
// 「バイナリデータの文字列」から「Base64」に変換する(同期実行)
// ------------------------------------------------------------
var base64 = Base64_From_StringOfBinaryData(string_of_binary);

// 出力テスト
console.log(base64); // "ARIjNEVWZ3iJmqu8zd7v"

// ------------------------------------------------------------
// 「バイナリデータの文字列」から「Base64」に変換する(非同期実行)
// ------------------------------------------------------------
Base64_From_StringOfBinaryData_Async(string_of_binary , function(base64){

	// 出力テスト
	console.log(base64); // "ARIjNEVWZ3iJmqu8zd7v"

});
 

■「Base64 文字列」から「バイナリデータの文字列」にデコード

 
■Base64 文字列から、バイナリデータの文字列に変換する
 
atob() メソッドを使用します。
 
「ASCII (Base64)」 to 「Binary (String)」 の略のようです。
 
このメソッドは、Internet Explorer 9 以前では未対応です。
 
Window.atob( "Base64 文字列" ) :String
第01引数 StringBase64 文字列を指定する。
戻り値 Stringバイナリデータの文字列が得られる。
 
■戻り値(バイナリデータの文字列)
 
バイナリデータの文字列が得られます。
 
バイト値を得るには、String.charCodeAt() メソッドを使用します。
 
■使用例
 
Base64 文字列からバイナリデータの文字列に変換する

// ------------------------------------------------------------
// Base64 文字列を用意する
// ------------------------------------------------------------
var base64 = "ARIjNEVWZ3iJmqu8zd7v";

// ------------------------------------------------------------
// 「Base64」から「バイナリデータの文字列」に変換する
// ------------------------------------------------------------
var string_of_binary = atob(base64);

// ------------------------------------------------------------
// 「バイナリデータの文字列」の中身を確認する
// ------------------------------------------------------------
var ary = new Array();
var i;
var num = string_of_binary.length;
for(i=0;i < num;i++){
	ary[i] = string_of_binary.charCodeAt(i);
}

// 出力テスト
console.log(ary); // [0x01,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9a,0xab,0xbc,0xcd,0xde,0xef]
 
■ atob() の代替関数
 
Internet Explorer 6 でも動作します。
 
Base64 文字列からバイナリデータの文字列に変換する関数

// ------------------------------------------------------------
// Base64 文字列からバイナリデータの文字列に変換する関数 (同期実行)
// ------------------------------------------------------------
function Base64_To_StringOfBinaryData(base64){
	var dic = new Object();
	dic[0x41]= 0; dic[0x42]= 1; dic[0x43]= 2; dic[0x44]= 3; dic[0x45]= 4; dic[0x46]= 5; dic[0x47]= 6; dic[0x48]= 7; dic[0x49]= 8; dic[0x4a]= 9; dic[0x4b]=10; dic[0x4c]=11; dic[0x4d]=12; dic[0x4e]=13; dic[0x4f]=14; dic[0x50]=15;
	dic[0x51]=16; dic[0x52]=17; dic[0x53]=18; dic[0x54]=19; dic[0x55]=20; dic[0x56]=21; dic[0x57]=22; dic[0x58]=23; dic[0x59]=24; dic[0x5a]=25; dic[0x61]=26; dic[0x62]=27; dic[0x63]=28; dic[0x64]=29; dic[0x65]=30; dic[0x66]=31;
	dic[0x67]=32; dic[0x68]=33; dic[0x69]=34; dic[0x6a]=35; dic[0x6b]=36; dic[0x6c]=37; dic[0x6d]=38; dic[0x6e]=39; dic[0x6f]=40; dic[0x70]=41; dic[0x71]=42; dic[0x72]=43; dic[0x73]=44; dic[0x74]=45; dic[0x75]=46; dic[0x76]=47;
	dic[0x77]=48; dic[0x78]=49; dic[0x79]=50; dic[0x7a]=51; dic[0x30]=52; dic[0x31]=53; dic[0x32]=54; dic[0x33]=55; dic[0x34]=56; dic[0x35]=57; dic[0x36]=58; dic[0x37]=59; dic[0x38]=60; dic[0x39]=61; dic[0x2b]=62; dic[0x2f]=63;
	var binary = [];
	var num = base64.length;
	var n = 0;
	var b = 0;
	var e;

	e = Math.ceil(num / 4) * 3;
	switch(num % 4){
	case 0:
		if(base64.charAt(num - 1) == '=') e -= 1;
		if(base64.charAt(num - 2) == '=') e -= 1;
		break;
	case 2:
		e -= 2;
		break;
	case 3:
		e -= 1;
		break;
	case 1:
		return null;
	}

	var i = 0;
	var p = 0;
	while(p < e){
		b = dic[base64.charCodeAt(i)];
		if(b === undefined) return null;
		n = (b << 2);
		i ++;

		b = dic[base64.charCodeAt(i)];
		if(b === undefined) return null;
		binary.push(String.fromCharCode(n | ((b >> 4) & 0x3)));
		n = (b & 0x0f) << 4;
		i ++;
		p ++;
		if(p >= e) break;

		b = dic[base64.charCodeAt(i)];
		if(b === undefined) return null;
		binary.push(String.fromCharCode(n | ((b >> 2) & 0xf)));
		n = (b & 0x03) << 6;
		i ++;
		p ++;
		if(p >= e) break;

		b = dic[base64.charCodeAt(i)];
		if(b === undefined) return null;
		binary.push(String.fromCharCode(n | b));
		i ++;
		p ++;
	}
	return binary.join("");
}

// ------------------------------------------------------------
// Base64 文字列からバイナリデータの文字列に変換する関数 (非同期実行)
// ------------------------------------------------------------
function Base64_To_StringOfBinaryData_Async(base64,callback,increment){
	var dic = new Object();
	dic[0x41]= 0; dic[0x42]= 1; dic[0x43]= 2; dic[0x44]= 3; dic[0x45]= 4; dic[0x46]= 5; dic[0x47]= 6; dic[0x48]= 7; dic[0x49]= 8; dic[0x4a]= 9; dic[0x4b]=10; dic[0x4c]=11; dic[0x4d]=12; dic[0x4e]=13; dic[0x4f]=14; dic[0x50]=15;
	dic[0x51]=16; dic[0x52]=17; dic[0x53]=18; dic[0x54]=19; dic[0x55]=20; dic[0x56]=21; dic[0x57]=22; dic[0x58]=23; dic[0x59]=24; dic[0x5a]=25; dic[0x61]=26; dic[0x62]=27; dic[0x63]=28; dic[0x64]=29; dic[0x65]=30; dic[0x66]=31;
	dic[0x67]=32; dic[0x68]=33; dic[0x69]=34; dic[0x6a]=35; dic[0x6b]=36; dic[0x6c]=37; dic[0x6d]=38; dic[0x6e]=39; dic[0x6f]=40; dic[0x70]=41; dic[0x71]=42; dic[0x72]=43; dic[0x73]=44; dic[0x74]=45; dic[0x75]=46; dic[0x76]=47;
	dic[0x77]=48; dic[0x78]=49; dic[0x79]=50; dic[0x7a]=51; dic[0x30]=52; dic[0x31]=53; dic[0x32]=54; dic[0x33]=55; dic[0x34]=56; dic[0x35]=57; dic[0x36]=58; dic[0x37]=59; dic[0x38]=60; dic[0x39]=61; dic[0x2b]=62; dic[0x2f]=63;
	var binary = [];
	var num = base64.length;
	var n = 0;
	var b = 0;
	var e;

	if(increment === undefined){
		increment = 10240;
	}
	
	e = Math.ceil(num / 4) * 3;
	switch(num % 4){
	case 0:
		if(base64.charAt(num - 1) == '=') e -= 1;
		if(base64.charAt(num - 2) == '=') e -= 1;
		break;
	case 2:
		e -= 2;
		break;
	case 3:
		e -= 1;
		break;
	case 1:
		callback(null);
		return;
	}

	var i = 0;
	var j = 0;
	var p = 0;
	function f(){
		while(p < e){
			b = dic[base64.charCodeAt(i)];
			if(b === undefined){ callback(null); return; }
			n = (b << 2);
			i ++;

			b = dic[base64.charCodeAt(i)];
			if(b === undefined){ callback(null); return; }
			binary.push(String.fromCharCode(n | ((b >> 4) & 0x3)));
			n = (b & 0x0f) << 4;
			i ++;
			p ++;
			if(p >= e) break;

			b = dic[base64.charCodeAt(i)];
			if(b === undefined){ callback(null); return; }
			binary.push(String.fromCharCode(n | ((b >> 2) & 0xf)));
			n = (b & 0x03) << 6;
			i ++;
			p ++;
			if(p >= e) break;

			b = dic[base64.charCodeAt(i)];
			if(b === undefined){ callback(null); return; }
			binary.push(String.fromCharCode(n | b));
			i ++;
			p ++;

			j += 4;
			if(j > increment){
				j = 0;
				setTimeout(f,1);
				return;
			}
		}
		callback(binary.join(""));
	}

	setTimeout(f,1);
}
 
使用例

// ------------------------------------------------------------
// Base64 文字列を用意する
// ------------------------------------------------------------
var base64 = "ARIjNEVWZ3iJmqu8zd7v";

// ------------------------------------------------------------
// 「Base64」から「バイナリデータの文字列」に変換する(同期実行)
// ------------------------------------------------------------
var string_of_binary = Base64_To_StringOfBinaryData(base64);

// ------------------------------------------------------------
// 「Base64」から「バイナリデータの文字列」に変換する(非同期実行)
// ------------------------------------------------------------
Base64_To_StringOfBinaryData_Async(base64 , function(string_of_binary){

});
 


 

Base64 と「x-user-defined 文字列」の相互変換

 
 


■「x-user-defined 文字列」について

 
■ x-user-defined とは?

バイナリを取り扱うための言語コードです。
 
1文字で1バイトを表現します。
 
以下の文字コードのみで構成されています。
 
U+0000(0) ~ U+007F(127)
 
U+F780(128) ~ U+F7FF(255)
 
上位1バイトは、環境によって異なる場合があります。
 
■1文字からバイト情報を得るには?
 
ユニコードで、下位1バイトのみを参照します。
 
位置を指定して文字コードを得るには、String.charCodeAt() メソッドを使用します。
 

■「x-user-defined 文字列」から「Base64 文字列」にエンコード

 
■「x-user-defined 文字列」から「Base64」にエンコードする関数

引数に、x-user-defined 文字列を指定します。
 
バイナリ形式に変換後、Base64 文字列にエンコードします。
 
Internet Explorer 6 でも動作します。
 
x-user-defined 文字列から Base64 文字列に変換する関数

// ------------------------------------------------------------
// x-user-defined 文字列から Base64 文字列に変換する関数 (同期実行)
// ------------------------------------------------------------
function Base64_From_XUserDefined(x_user_defined){
	var dic = [
		'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
		'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
		'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
		'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
	];
	var base64 = [];
	var num = x_user_defined.length;
	var n = 0;
	var b = 0;

	var i = 0;
	while(i < num){
		b = x_user_defined.charCodeAt(i) & 0xff;
		base64.push(dic[(b >> 2)]);
		n = (b & 0x03) << 4;
		i ++;
		if(i >= num) break;

		b = x_user_defined.charCodeAt(i) & 0xff;
		base64.push(dic[n | (b >> 4)]);
		n = (b & 0x0f) << 2;
		i ++;
		if(i >= num) break;

		b = x_user_defined.charCodeAt(i) & 0xff;
		base64.push(dic[n | (b >> 6)]);
		base64.push(dic[(b & 0x3f)]);
		i ++;
	}

	var m = num % 3;
	if(m){
		base64.push(dic[n]);
	}
	if(m == 1){
		base64.push("==");
	}else if(m == 2){
		base64.push("=");
	}
	return base64.join("");
}

// ------------------------------------------------------------
// x-user-defined 文字列から Base64 文字列に変換する関数 (非同期実行)
// ------------------------------------------------------------
function Base64_From_XUserDefined_Async(x_user_defined,callback,increment){
	var dic = [
		'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
		'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
		'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
		'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
	];
	var base64 = [];
	var num = x_user_defined.length;
	var n = 0;
	var b = 0;

	if(increment === undefined){
		increment = 10240;
	}

	var i = 0;
	var j = 0;
	function f(){
		while(i < num){
			b = x_user_defined.charCodeAt(i) & 0xff;
			base64.push(dic[(b >> 2)]);
			n = (b & 0x03) << 4;
			i ++;
			if(i >= num) break;

			b = x_user_defined.charCodeAt(i) & 0xff;
			base64.push(dic[n | (b >> 4)]);
			n = (b & 0x0f) << 2;
			i ++;
			if(i >= num) break;

			b = x_user_defined.charCodeAt(i) & 0xff;
			base64.push(dic[n | (b >> 6)]);
			base64.push(dic[(b & 0x3f)]);
			i ++;

			j += 3;
			if(j > increment){
				j = 0;
				setTimeout(f,1);
				return;
			}
		}

		var m = num % 3;
		if(m){
			base64.push(dic[n]);
		}
		if(m == 1){
			base64.push("==");
		}else if(m == 2){
			base64.push("=");
		}
		callback(base64.join(""));
	}

	setTimeout(f,1);
}
 
使用例

// ------------------------------------------------------------
// 配列を用意する
// ------------------------------------------------------------
var ary = [0x01,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9a,0xab,0xbc,0xcd,0xde,0xef];

// ------------------------------------------------------------
// 「x-user-defined 文字列」を作成する
// ------------------------------------------------------------
var x_user_defined = "";
var i;
var num = ary.length;
for(i=0;i < num;i++){
	var lower = ary[i]; 
	var upper = (lower >= 0x80) ? 0xF7 : 0x00;
	var code = (upper << 8) | lower;
	x_user_defined += String.fromCharCode(code);
}

// ------------------------------------------------------------
// 「x-user-defined 文字列」から「Base64」に変換する(同期実行)
// ------------------------------------------------------------
var base64 = Base64_From_XUserDefined(x_user_defined);

// 出力テスト
console.log(base64); // "ARIjNEVWZ3iJmqu8zd7v"

// ------------------------------------------------------------
// 「x-user-defined 文字列」から「Base64」に変換する(非同期実行)
// ------------------------------------------------------------
Base64_From_XUserDefined_Async(x_user_defined , function(base64){

	// 出力テスト
	console.log(base64); // "ARIjNEVWZ3iJmqu8zd7v"

});
 

■「Base64 文字列」から「x-user-defined 文字列」にデコード

 
■「Base64 文字列」から「x-user-defined 文字列」にデコードする関数

引数に、バイナリをエンコードした Base64 文字列を指定します。
 
不正なデータである場合、null 値が得られます。
 
Internet Explorer 6 でも動作します。
 
Base64 文字列からx-user-defined 文字列に変換する関数

// ------------------------------------------------------------
// Base64 文字列から x-user-defined 文字列に変換する関数 (同期実行)
// ------------------------------------------------------------
function Base64_To_XUserDefined(base64){
	var dic = new Object();
	dic[0x41]= 0; dic[0x42]= 1; dic[0x43]= 2; dic[0x44]= 3; dic[0x45]= 4; dic[0x46]= 5; dic[0x47]= 6; dic[0x48]= 7; dic[0x49]= 8; dic[0x4a]= 9; dic[0x4b]=10; dic[0x4c]=11; dic[0x4d]=12; dic[0x4e]=13; dic[0x4f]=14; dic[0x50]=15;
	dic[0x51]=16; dic[0x52]=17; dic[0x53]=18; dic[0x54]=19; dic[0x55]=20; dic[0x56]=21; dic[0x57]=22; dic[0x58]=23; dic[0x59]=24; dic[0x5a]=25; dic[0x61]=26; dic[0x62]=27; dic[0x63]=28; dic[0x64]=29; dic[0x65]=30; dic[0x66]=31;
	dic[0x67]=32; dic[0x68]=33; dic[0x69]=34; dic[0x6a]=35; dic[0x6b]=36; dic[0x6c]=37; dic[0x6d]=38; dic[0x6e]=39; dic[0x6f]=40; dic[0x70]=41; dic[0x71]=42; dic[0x72]=43; dic[0x73]=44; dic[0x74]=45; dic[0x75]=46; dic[0x76]=47;
	dic[0x77]=48; dic[0x78]=49; dic[0x79]=50; dic[0x7a]=51; dic[0x30]=52; dic[0x31]=53; dic[0x32]=54; dic[0x33]=55; dic[0x34]=56; dic[0x35]=57; dic[0x36]=58; dic[0x37]=59; dic[0x38]=60; dic[0x39]=61; dic[0x2b]=62; dic[0x2f]=63;
	var x_user_defined = [];
	var num = base64.length;
	var n = 0;
	var b = 0;
	var e;

	e = Math.ceil(num / 4) * 3;
	switch(num % 4){
	case 0:
		if(base64.charAt(num - 1) == '=') e -= 1;
		if(base64.charAt(num - 2) == '=') e -= 1;
		break;
	case 2:
		e -= 2;
		break;
	case 3:
		e -= 1;
		break;
	case 1:
		return null;
	}

	var i = 0;
	var p = 0;
	while(p < e){
		b = dic[base64.charCodeAt(i)];
		if(b === undefined) return null;
		n = (b << 2);
		i ++;

		b = dic[base64.charCodeAt(i)];
		if(b === undefined) return null;
		n |= (b >> 4) & 0x3;
		x_user_defined.push(String.fromCharCode((n < 0x80) ? (n) : (0xf700 | n)));
		n = (b & 0x0f) << 4;
		i ++;
		p ++;
		if(p >= e) break;

		b = dic[base64.charCodeAt(i)];
		if(b === undefined) return null;
		n |= (b >> 2) & 0xf;
		x_user_defined.push(String.fromCharCode((n < 0x80) ? (n) : (0xf700 | n)));
		n = (b & 0x03) << 6;
		i ++;
		p ++;
		if(p >= e) break;

		b = dic[base64.charCodeAt(i)];
		if(b === undefined) return null;
		n |= b;
		x_user_defined.push(String.fromCharCode((n < 0x80) ? (n) : (0xf700 | n)));
		i ++;
		p ++;
	}
	return x_user_defined.join("");
}

// ------------------------------------------------------------
// Base64 文字列から x-user-defined 文字列に変換する関数 (非同期実行)
// ------------------------------------------------------------
function Base64_To_XUserDefined_Async(base64,callback,increment){
	var dic = new Object();
	dic[0x41]= 0; dic[0x42]= 1; dic[0x43]= 2; dic[0x44]= 3; dic[0x45]= 4; dic[0x46]= 5; dic[0x47]= 6; dic[0x48]= 7; dic[0x49]= 8; dic[0x4a]= 9; dic[0x4b]=10; dic[0x4c]=11; dic[0x4d]=12; dic[0x4e]=13; dic[0x4f]=14; dic[0x50]=15;
	dic[0x51]=16; dic[0x52]=17; dic[0x53]=18; dic[0x54]=19; dic[0x55]=20; dic[0x56]=21; dic[0x57]=22; dic[0x58]=23; dic[0x59]=24; dic[0x5a]=25; dic[0x61]=26; dic[0x62]=27; dic[0x63]=28; dic[0x64]=29; dic[0x65]=30; dic[0x66]=31;
	dic[0x67]=32; dic[0x68]=33; dic[0x69]=34; dic[0x6a]=35; dic[0x6b]=36; dic[0x6c]=37; dic[0x6d]=38; dic[0x6e]=39; dic[0x6f]=40; dic[0x70]=41; dic[0x71]=42; dic[0x72]=43; dic[0x73]=44; dic[0x74]=45; dic[0x75]=46; dic[0x76]=47;
	dic[0x77]=48; dic[0x78]=49; dic[0x79]=50; dic[0x7a]=51; dic[0x30]=52; dic[0x31]=53; dic[0x32]=54; dic[0x33]=55; dic[0x34]=56; dic[0x35]=57; dic[0x36]=58; dic[0x37]=59; dic[0x38]=60; dic[0x39]=61; dic[0x2b]=62; dic[0x2f]=63;
	var x_user_defined = [];
	var num = base64.length;
	var n = 0;
	var b = 0;
	var e;

	if(increment === undefined){
		increment = 10240;
	}

	e = Math.ceil(num / 4) * 3;
	switch(num % 4){
	case 0:
		if(base64.charAt(num - 1) == '=') e -= 1;
		if(base64.charAt(num - 2) == '=') e -= 1;
		break;
	case 2:
		e -= 2;
		break;
	case 3:
		e -= 1;
		break;
	case 1:
		callback(null);
		return;
	}

	var i = 0;
	var j = 0;
	var p = 0;
	function f(){
		while(p < e){
			b = dic[base64.charCodeAt(i)];
			if(b === undefined){ callback(null); return; }
			n = (b << 2);
			i ++;

			b = dic[base64.charCodeAt(i)];
			if(b === undefined){ callback(null); return; }
			n |= (b >> 4) & 0x3;
			x_user_defined.push(String.fromCharCode((n < 0x80) ? (n) : (0xf700 | n)));
			n = (b & 0x0f) << 4;
			i ++;
			p ++;
			if(p >= e) break;

			b = dic[base64.charCodeAt(i)];
			if(b === undefined){ callback(null); return; }
			n |= (b >> 2) & 0xf;
			x_user_defined.push(String.fromCharCode((n < 0x80) ? (n) : (0xf700 | n)));
			n = (b & 0x03) << 6;
			i ++;
			p ++;
			if(p >= e) break;

			b = dic[base64.charCodeAt(i)];
			if(b === undefined){ callback(null); return; }
			n |= b;
			x_user_defined.push(String.fromCharCode((n < 0x80) ? (n) : (0xf700 | n)));
			i ++;
			p ++;

			j += 4;
			if(j > increment){
				j = 0;
				setTimeout(f,1);
				return;
			}
		}
		callback(x_user_defined.join(""));
	}

	setTimeout(f,1);
}
 
使用例

// ------------------------------------------------------------
// Base64 文字列を用意する
// ------------------------------------------------------------
var base64 = "ARIjNEVWZ3iJmqu8zd7v";

// ------------------------------------------------------------
// 「Base64」から「x-user-defined 文字列」に変換する(同期実行)
// ------------------------------------------------------------
var x_user_defined = Base64_To_XUserDefined(base64);

// ------------------------------------------------------------
// 「Base64」から「x-user-defined 文字列」に変換する(非同期実行)
// ------------------------------------------------------------
Base64_To_XUserDefined_Async(base64 , function(x_user_defined){

});

// ------------------------------------------------------------
// 「x-user-defined 文字列」の中身を確認する
// ------------------------------------------------------------
var ary = new Array();
var i;
var num = x_user_defined.length;
for(i=0;i < num;i++){
	ary[i] = x_user_defined.charCodeAt(i) & 0xff;
}

// 出力テスト
console.log(ary); // [0x01,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9a,0xab,0xbc,0xcd,0xde,0xef]
 


 

Base64 と「ArrayBuffer」の相互変換

 
 


■「ArrayBuffer」について

 
■ ArrayBuffer クラスについて
 
バイナリデータを取り扱う事ができます。
 
詳しくは、こちらで解説しています。
 

■「ArrayBuffer」から「Base64 文字列」にエンコード

 
■「ArrayBuffer」から「Base64」にエンコードする関数

引数に、ArrayBuffer オブジェクトを指定します。
 
ArrayBuffer から Base64 文字列に変換する関数

// ------------------------------------------------------------
// ArrayBuffer から Base64 文字列に変換する関数 (同期実行)
// ------------------------------------------------------------
function Base64_From_ArrayBuffer(ary_buffer){
	var dic = [
		'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
		'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
		'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
		'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
	];
	var base64 = [];
	var ary_u8 = new Uint8Array( ary_buffer );
	var num = ary_u8.length;
	var n = 0;
	var b = 0;

	var i = 0;
	while(i < num){
		b = ary_u8[i];
		base64.push(dic[(b >> 2)]);
		n = (b & 0x03) << 4;
		i ++;
		if(i >= num) break;

		b = ary_u8[i];
		base64.push(dic[n | (b >> 4)]);
		n = (b & 0x0f) << 2;
		i ++;
		if(i >= num) break;

		b = ary_u8[i];
		base64.push(dic[n | (b >> 6)]);
		base64.push(dic[(b & 0x3f)]);
		i ++;
	}

	var m = num % 3;
	if(m){
		base64.push(dic[n]);
	}
	if(m == 1){
		base64.push("==");
	}else if(m == 2){
		base64.push("=");
	}
	return base64.join("");
}

// ------------------------------------------------------------
// ArrayBuffer から Base64 文字列に変換する関数 (非同期実行)
// ------------------------------------------------------------
function Base64_From_ArrayBuffer_Async(ary_buffer,callback,increment){
	var dic = [
		'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
		'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
		'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
		'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
	];
	var base64 = [];
	var ary_u8 = new Uint8Array( ary_buffer );
	var num = ary_u8.length;
	var n = 0;
	var b = 0;

	if(increment === undefined){
		increment = 10240;
	}

	var i = 0;
	var j = 0;
	function f(){
		while(i < num){
			b = ary_u8[i];
			base64.push(dic[(b >> 2)]);
			n = (b & 0x03) << 4;
			i ++;
			if(i >= num) break;

			b = ary_u8[i];
			base64.push(dic[n | (b >> 4)]);
			n = (b & 0x0f) << 2;
			i ++;
			if(i >= num) break;

			b = ary_u8[i];
			base64.push(dic[n | (b >> 6)]);
			base64.push(dic[(b & 0x3f)]);
			i ++;

			j += 3;
			if(j > increment){
				j = 0;
				setTimeout(f,1);
				return;
			}
		}

		var m = num % 3;
		if(m){
			base64.push(dic[n]);
		}
		if(m == 1){
			base64.push("==");
		}else if(m == 2){
			base64.push("=");
		}
		callback(base64.join(""));
	}

	setTimeout(f,1);
}
 
使用例

// ------------------------------------------------------------
// Uint8Array オブジェクトを作成
// ------------------------------------------------------------
var ary_u8 = new Uint8Array([0x01,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9a,0xab,0xbc,0xcd,0xde,0xef]);

// ArrayBuffer オブジェクトを取得
var ary_buffer = ary_u8.buffer;

// ------------------------------------------------------------
// 「ArrayBuffer」から「Base64」に変換する(同期実行)
// ------------------------------------------------------------
var base64 = Base64_From_ArrayBuffer(ary_buffer);

// 出力テスト
console.log(base64); // "ARIjNEVWZ3iJmqu8zd7v"

// ------------------------------------------------------------
// 「ArrayBuffer」から「Base64」に変換する(非同期実行)
// ------------------------------------------------------------
Base64_From_ArrayBuffer_Async(ary_buffer , function(base64){

	// 出力テスト
	console.log(base64); // "ARIjNEVWZ3iJmqu8zd7v"

});
 

■「Base64 文字列」から「ArrayBuffer」にデコード

 
■「Base64 文字列」から「ArrayBuffer」にデコードする関数

引数に、Base64 文字列を指定します。
 
不正なデータである場合、null 値が得られます。
 
Base64 文字列からArrayBufferに変換する関数

// ------------------------------------------------------------
// Base64 文字列から ArrayBuffer に変換する関数 (同期実行)
// ------------------------------------------------------------
function Base64_To_ArrayBuffer(base64){
	var dic = new Object();
	dic[0x41]= 0; dic[0x42]= 1; dic[0x43]= 2; dic[0x44]= 3; dic[0x45]= 4; dic[0x46]= 5; dic[0x47]= 6; dic[0x48]= 7; dic[0x49]= 8; dic[0x4a]= 9; dic[0x4b]=10; dic[0x4c]=11; dic[0x4d]=12; dic[0x4e]=13; dic[0x4f]=14; dic[0x50]=15;
	dic[0x51]=16; dic[0x52]=17; dic[0x53]=18; dic[0x54]=19; dic[0x55]=20; dic[0x56]=21; dic[0x57]=22; dic[0x58]=23; dic[0x59]=24; dic[0x5a]=25; dic[0x61]=26; dic[0x62]=27; dic[0x63]=28; dic[0x64]=29; dic[0x65]=30; dic[0x66]=31;
	dic[0x67]=32; dic[0x68]=33; dic[0x69]=34; dic[0x6a]=35; dic[0x6b]=36; dic[0x6c]=37; dic[0x6d]=38; dic[0x6e]=39; dic[0x6f]=40; dic[0x70]=41; dic[0x71]=42; dic[0x72]=43; dic[0x73]=44; dic[0x74]=45; dic[0x75]=46; dic[0x76]=47;
	dic[0x77]=48; dic[0x78]=49; dic[0x79]=50; dic[0x7a]=51; dic[0x30]=52; dic[0x31]=53; dic[0x32]=54; dic[0x33]=55; dic[0x34]=56; dic[0x35]=57; dic[0x36]=58; dic[0x37]=59; dic[0x38]=60; dic[0x39]=61; dic[0x2b]=62; dic[0x2f]=63;
	var num = base64.length;
	var n = 0;
	var b = 0;
	var e;

	e = Math.ceil(num / 4) * 3;
	switch(num % 4){
	case 0:
		if(base64.charAt(num - 1) == '=') e -= 1;
		if(base64.charAt(num - 2) == '=') e -= 1;
		break;
	case 2:
		e -= 2;
		break;
	case 3:
		e -= 1;
		break;
	case 1:
		return null;
	}

	var ary_buffer = new ArrayBuffer( e );
	var ary_u8 = new Uint8Array( ary_buffer );
	var i = 0;
	var p = 0;
	while(p < e){
		b = dic[base64.charCodeAt(i)];
		if(b === undefined) return null;
		n = (b << 2);
		i ++;

		b = dic[base64.charCodeAt(i)];
		if(b === undefined) return null;
		ary_u8[p] = n | ((b >> 4) & 0x3);
		n = (b & 0x0f) << 4;
		i ++;
		p ++;
		if(p >= e) break;

		b = dic[base64.charCodeAt(i)];
		if(b === undefined) return null;
		ary_u8[p] = n | ((b >> 2) & 0xf);
		n = (b & 0x03) << 6;
		i ++;
		p ++;
		if(p >= e) break;

		b = dic[base64.charCodeAt(i)];
		if(b === undefined) return null;
		ary_u8[p] = n | b;
		i ++;
		p ++;
	}
	return ary_buffer;
}

// ------------------------------------------------------------
// Base64 文字列から ArrayBuffer に変換する関数 (非同期実行)
// ------------------------------------------------------------
function Base64_To_ArrayBuffer_Async(base64,callback,increment){
	var dic = new Object();
	dic[0x41]= 0; dic[0x42]= 1; dic[0x43]= 2; dic[0x44]= 3; dic[0x45]= 4; dic[0x46]= 5; dic[0x47]= 6; dic[0x48]= 7; dic[0x49]= 8; dic[0x4a]= 9; dic[0x4b]=10; dic[0x4c]=11; dic[0x4d]=12; dic[0x4e]=13; dic[0x4f]=14; dic[0x50]=15;
	dic[0x51]=16; dic[0x52]=17; dic[0x53]=18; dic[0x54]=19; dic[0x55]=20; dic[0x56]=21; dic[0x57]=22; dic[0x58]=23; dic[0x59]=24; dic[0x5a]=25; dic[0x61]=26; dic[0x62]=27; dic[0x63]=28; dic[0x64]=29; dic[0x65]=30; dic[0x66]=31;
	dic[0x67]=32; dic[0x68]=33; dic[0x69]=34; dic[0x6a]=35; dic[0x6b]=36; dic[0x6c]=37; dic[0x6d]=38; dic[0x6e]=39; dic[0x6f]=40; dic[0x70]=41; dic[0x71]=42; dic[0x72]=43; dic[0x73]=44; dic[0x74]=45; dic[0x75]=46; dic[0x76]=47;
	dic[0x77]=48; dic[0x78]=49; dic[0x79]=50; dic[0x7a]=51; dic[0x30]=52; dic[0x31]=53; dic[0x32]=54; dic[0x33]=55; dic[0x34]=56; dic[0x35]=57; dic[0x36]=58; dic[0x37]=59; dic[0x38]=60; dic[0x39]=61; dic[0x2b]=62; dic[0x2f]=63;
	var num = base64.length;
	var n = 0;
	var b = 0;
	var e;

	if(increment === undefined){
		increment = 10240;
	}

	e = Math.ceil(num / 4) * 3;
	switch(num % 4){
	case 0:
		if(base64.charAt(num - 1) == '=') e -= 1;
		if(base64.charAt(num - 2) == '=') e -= 1;
		break;
	case 2:
		e -= 2;
		break;
	case 3:
		e -= 1;
		break;
	case 1:
		callback(null);
		return;
	}

	var ary_buffer = new ArrayBuffer( e );
	var ary_u8 = new Uint8Array( ary_buffer );
	var i = 0;
	var j = 0;
	var p = 0;
	function f(){
		while(p < e){
			b = dic[base64.charCodeAt(i)];
			if(b === undefined){ callback(null); return; }
			n = (b << 2);
			i ++;

			b = dic[base64.charCodeAt(i)];
			if(b === undefined){ callback(null); return; }
			ary_u8[p] = n | ((b >> 4) & 0x3);
			n = (b & 0x0f) << 4;
			i ++;
			p ++;
			if(p >= e) break;

			b = dic[base64.charCodeAt(i)];
			if(b === undefined){ callback(null); return; }
			ary_u8[p] = n | ((b >> 2) & 0xf);
			n = (b & 0x03) << 6;
			i ++;
			p ++;
			if(p >= e) break;

			b = dic[base64.charCodeAt(i)];
			if(b === undefined){ callback(null); return; }
			ary_u8[p] = n | b;
			i ++;
			p ++;

			j += 4;
			if(j > increment){
				j = 0;
				setTimeout(f,1);
				return;
			}
		}
		callback(ary_buffer);
	}

	setTimeout(f,1);
}
 
使用例

// ------------------------------------------------------------
// Base64 文字列を用意する
// ------------------------------------------------------------
var base64 = "ARIjNEVWZ3iJmqu8zd7v";

// ------------------------------------------------------------
// 「Base64」から「ArrayBuffer」に変換する(同期実行)
// ------------------------------------------------------------
var ary_buffer = Base64_To_ArrayBuffer(base64);

// ------------------------------------------------------------
// 「Base64」から「ArrayBuffer」に変換する(非同期実行)
// ------------------------------------------------------------
Base64_To_ArrayBuffer_Async(base64 , function(ary_buffer){

});

// ------------------------------------------------------------
// 「ArrayBuffer」の中身を確認する
// ------------------------------------------------------------
var ary_u8 = new Uint8Array(ary_buffer);

// 出力テスト
console.log(ary_u8); // [0x01,0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9a,0xab,0xbc,0xcd,0xde,0xef]