JavaScript プログラミング講座

 

Data URI Scheme とは?

 


■Data URI Scheme とは?


Data URI Scheme は、URI スキームの一種です。
 
「コンテンツタイプ」と「バイナリ」の2つの情報を、URI 文字列の中にすべて埋め込む事ができます
 
■Data URI Scheme を活用する
 
URL アドレスを指定可能な場所には、Data URI Scheme を指定する事もできます。
 
例えば、<IMG> 要素の src プロパティにセットすると、画像として表示することができます。
 
<img> 要素の src 属性に、Data URI Scheme を指定する

<html>
  <body>

    <img src="data:image/gif;base64,R0lGODlhIAAgALMAAAAAAMHi9zYA2WZmZre3t/v+/93w/4eHh8zMzP///wAAAAAAAAAAAAAAAAAAAAAAACH5BAEHAAIALAAAAAAgACAAAATVUEgBqq1z3g1y5pgHWh4FGKiRrAl3vAchz6FUpSrrwjPdmTgcqwUYDGA8n+0URA0rRuSrF6oEAs1n0XiUUi3XrG4b9fqsV2yKw+Uiv+jwetMuT88jJipvgedxfBV+ck2FQSsjhIaLiCBXHIYjWmiQhZJjFwiaCBeAAJqZnACNoaAWnqYVpqQWQ41ijbFEF65EsESyF4+jtosVWqy7r768uWBpi8k5wcjKhpMAaWrOe0zQ0tRzTmNLioF6OTUm3oFCRCWd2QYXJUs36uztH98k8u309SURADs=" >

  </body>
</html>
 
■Data URI Scheme の利点
 
URL アドレスから Data URI Scheme に変更すると、そのファイルの読み込み通信が発生しなくなります
 
Data URI Scheme を採用すればするほど、読み込み回数が減り、高速化が期待できます
 
■Data URI Scheme の注意点
 
ファイルサイズが巨大な場合は、採用しないほうがいいでしょう。
 
Data URI 文字列のサイズは、通常のファイルサイズよりも、必ず大きくなります。(約 4/3 倍)
 
■対応状況
 
古いブラウザであるほど、問題や制限があります。
 
Internet Explorer 8 の場合、CSS や <IMG> などの一部の要素にしか対応していません。
 
Internet Explorer 8 の場合、文字数に上限(約32KByte)があります。
 
Internet Explorer 7 以前では、未対応です。
 


 

Data URI Scheme のフォーマットについて

 


■Data URI Scheme のフォーマットについて

 
■スキームの指定(必須)
 
まず、『 data: 』と記述します。スキームの指定は必須です。
 
これで、Data URI Scheme を意味します。
 
■コンテンツタイプの指定(省略可)
 
次に データの MIME タイプを指定します。省略可能です。
 
省略した場合、『 text/plain;charset=US-ASCII 』が採用されます。
 
■文字セットの指定(省略可)
 
次に、データの文字セットを指定します。省略可能です。
 
;charset=文字セット 』と記述します。
 
■書式の指定(省略可)
 
次に、データの書式を指定します。省略可能です。
 
省略した場合、データは、Percent-Encoding となります。
 
;base64 』と記述した場合、データは、Base64 となります。
 
■データの指定(必須)
 
最後に、データを記述します。
 
カンマ『 , 』を記述して、続けて任意のデータを記述します。
 
任意の文字列を Percent-Encoding に変換するには、encodeURIComponent() メソッドを使用します。
 
任意の文字列を Base64 にエンコードする方法については、こちらで解説しています。
 
■Data URI Scheme の記述例
 
HTML ファイル(文字コード:US-ASCII、書式:Percent-Encoding)

data:text/html,<html><body>test</body></html>
 
プレーンテキストファイル(文字コード:UTF-8、書式:Percent-Encoding)

data:text/plain;charset=UTF-8,%E3%81%82%E3%81%84%E3%81%86%E3%81%88%E3%81%8A
 
プレーンテキストファイル(文字コード:UTF-8、書式:Base64)

data:text/plain;charset=UTF-8;base64,44GC44GE44GG44GI44GK
 
GIF 画像ファイル(書式:Base64)

data:image/gif;base64,R0lGODlhIAAgALMAAAAAAMHi9zYA2WZmZre3t/v+/93w/4eHh8zMzP///wAAAAAAAAAAAAAAAAAAAAAAACH5BAEHAAIALAAAAAAgACAAAATVUEgBqq1z3g1y5pgHWh4FGKiRrAl3vAchz6FUpSrrwjPdmTgcqwUYDGA8n+0URA0rRuSrF6oEAs1n0XiUUi3XrG4b9fqsV2yKw+Uiv+jwetMuT88jJipvgedxfBV+ck2FQSsjhIaLiCBXHIYjWmiQhZJjFwiaCBeAAJqZnACNoaAWnqYVpqQWQ41ijbFEF65EsESyF4+jtosVWqy7r768uWBpi8k5wcjKhpMAaWrOe0zQ0tRzTmNLioF6OTUm3oFCRCWd2QYXJUs36uztH98k8u309SURADs=
 


 

ローカルファイルから Data URI Scheme を生成する

 
 


■ローカルファイルから Data URI Scheme を生成する


File オブジェクトを取得する方法については、こちらで解説しています。
 
FileReader クラスを使って、Data URI Scheme を生成する方法については、こちらで解説しています。
 
FileReader クラスは、Safari 5 以前では、未対応です。
 
FileReader クラスは、Internet Explorer 9 以前では、未対応です。
 
■取得例
 
ファイルを読み込み、Data URI Scheme 文字列を得る

<html>
  <body>

    <form>

      <input type="file" id="aaa" >

    </form>

    <script type="text/javascript">
    <!--
	// "aaa" という ID 属性のエレメントを取得する
	var input_file = document.getElementById("aaa");

	// ------------------------------------------------------------
	// 値が変化した時に実行されるイベント
	// ------------------------------------------------------------
	input_file.onchange = function (){

		// ファイルが選択されたか
		if(!(input_file.value)) return;

		// FileReader クラスに対応しているか
		if(!(window.FileReader)) return;

		// ------------------------------------------------------------
		// File オブジェクトを取得(HTML5 世代)
		// ------------------------------------------------------------
		// ファイルリストを取得
		var file_list = input_file.files;
		if(!file_list) return;

		// 0 番目の File オブジェクトを取得
		var file = file_list[0];
		if(!file) return;

		// ------------------------------------------------------------
		// FileReader オブジェクトを生成
		// ------------------------------------------------------------
		var file_reader = new FileReader();

		// ------------------------------------------------------------
		// 読み込み成功時に実行されるイベント
		// ------------------------------------------------------------
		file_reader.onload = function(e){

			// 出力テスト
			console.log(file_reader.result);
		};

		// ------------------------------------------------------------
		// 読み込みを開始する(Data URI Scheme 文字列を得る)
		// ------------------------------------------------------------
		file_reader.readAsDataURL(file);
	};

    //-->
    </script>

  </body>
</html>
 


 

外部ファイルから Data URI Scheme を生成する

 
 
 


■「XMLHttpRequest Level2」 + 「FileReader クラス」を使用する

 
Cross-Origin 特権付き XMLHttpRequest で利用すると便利です。(拡張機能用の JavaScript など)
 
Safari 5 では、こちらを使用します。
 
まず XMLHttpRequest を使って、Blob オブジェクトを取得します。
 
Blob オブジェクトを取得する方法については、こちらで解説しています。
 
次に、FileReader クラスを使って、Data URI Scheme を生成します。
 
Data URI Scheme を生成する方法については、こちらで解説しています。
 
XMLHttpRequest と FileReader クラスを使って、Data URI Scheme 文字列を得る

// ------------------------------------------------------------
// XMLHttpRequest オブジェクトを作成する
// ------------------------------------------------------------
var xhr = new XMLHttpRequest();

// ------------------------------------------------------------
// XMLHttpRequest の受信が成功した時に実行されるイベント
// ------------------------------------------------------------
xhr.onload = function(){

	// ------------------------------------------------------------
	// 受信した Blob オブジェクトを取得する
	// ------------------------------------------------------------
	var blob = xhr.response;

	// ------------------------------------------------------------
	// FileReader オブジェクトを生成
	// ------------------------------------------------------------
	var file_reader = new FileReader();

	// ------------------------------------------------------------
	// 読み込み成功時に実行されるイベント
	// ------------------------------------------------------------
	file_reader.onload = function(e){

		// 出力テスト
		console.log(file_reader.result);
	};

	// ------------------------------------------------------------
	// 読み込みを開始する(Data URI Scheme 文字列を得る)
	// ------------------------------------------------------------
	file_reader.readAsDataURL(blob);
};

// ------------------------------------------------------------
// HTTP メソッドを指定、アクセス先を指定
// ------------------------------------------------------------
xhr.open("GET","https://hakuhin.jp/graphic/title.png");

// ------------------------------------------------------------
// 受信データのタイプを指定
// ------------------------------------------------------------
xhr.responseType = "blob";

// ------------------------------------------------------------
// 送信データを指定し、通信を開始する
// ------------------------------------------------------------
xhr.send(null);
 

■「XMLHttpRequest Level2」 + 「ArrayBuffer クラス」を使用する

 
Cross-Origin 特権付き XMLHttpRequest で利用すると便利です。(拡張機能用の JavaScript など)
 
まず XMLHttpRequest を使って、ArrayBuffer オブジェクトを取得します。
 
ArrayBuffer オブジェクトを取得する方法については、こちらで解説しています。
 
次に、ArrayBuffer から Base64 文字列にエンコードします。
 
Base64 文字列に変換する方法については、こちらで解説しています。
 
XMLHttpRequest から、コンテンツタイプを取得するには、レスポンスヘッダを取得します。
 
レスポンスヘッダを取得する方法については、こちらで解説しています。
 
XMLHttpRequest と ArrayBuffer クラスを使って、Data URI Scheme 文字列を得る

// ------------------------------------------------------------
// 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 += dic[(b >> 2)];
			n = (b & 0x03) << 4;
			i ++;
			if(i >= num) break;

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

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

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

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

	setTimeout(f,1);
}


// ------------------------------------------------------------
// XMLHttpRequest オブジェクトを作成する
// ------------------------------------------------------------
var xhr = new XMLHttpRequest();

// ------------------------------------------------------------
// XMLHttpRequest の受信が成功した時に実行されるイベント
// ------------------------------------------------------------
xhr.onload = function(){

	// ------------------------------------------------------------
	// 受信した ArrayBuffer オブジェクトを取得する
	// ------------------------------------------------------------
	var array_buffer = xhr.response;

	// ------------------------------------------------------------
	// ArrayBuffer から Base64 文字列に変換する (非同期実行)
	// ------------------------------------------------------------
	Base64_From_ArrayBuffer_Async(array_buffer,function(base64){

		var data_url = "data:" + xhr.getResponseHeader("Content-Type") + ";base64," + base64;

		// 出力テスト
		console.log(data_url);

	});

};

// ------------------------------------------------------------
// HTTP メソッドを指定、アクセス先を指定
// ------------------------------------------------------------
xhr.open("GET","https://hakuhin.jp/graphic/title.png");

// ------------------------------------------------------------
// 受信データのタイプを指定
// ------------------------------------------------------------
xhr.responseType = "arraybuffer";

// ------------------------------------------------------------
// 送信データを指定し、通信を開始する
// ------------------------------------------------------------
xhr.send(null);
 

■「XMLHttpRequest Level2」 + 「x-user-defined 文字列」を使用する

 
Greasemonkey スクリプトでも利用可能です。
 
Internet Explorer 10 では、こちらを使用します。
 
まず XMLHttpRequest を使って、「x-user-defined 文字列」を取得します。
 
overrideMimeType() メソッドの引数に、"text/plain; charset=x-user-defined" を指定します。
 
次に、「x-user-defined 文字列」から Base64 文字列にエンコードします。
 
Base64 文字列に変換する方法については、こちらで解説しています。
 
XMLHttpRequest から、コンテンツタイプを取得するには、レスポンスヘッダを取得します。
 
レスポンスヘッダを取得する方法については、こちらで解説しています。
 
XMLHttpRequest と x-user-defined 文字列を使って、Data URI Scheme 文字列を得る

// ------------------------------------------------------------
// 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 += dic[(b >> 2)];
			n = (b & 0x03) << 4;
			i ++;
			if(i >= num) break;

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

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

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

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

	setTimeout(f,1);
}

// ------------------------------------------------------------
// レスポンスヘッダから Object に変換する関数
// ------------------------------------------------------------
function ResponseHeadersParseObject(str){
	var o = new Object();
	if(!str)	return o;

	// 改行コードを統一
	var s = str.replace(/\r\n?/g,"\n");
	var a = s.split("\n");
	var i;
	var num = a.length;
	for(i=0;i < num;i++){
		var m = a[i].match(new RegExp("^(.*):[ ](.*)$","i"));
		if(m){
			o[m[1]] = m[2];
		}
	}
	return o;
}


if(1){

	// ------------------------------------------------------------
	// XMLHttpRequest オブジェクトを作成する
	// ------------------------------------------------------------
	var xhr = new XMLHttpRequest();

	// ------------------------------------------------------------
	// XMLHttpRequest の受信が成功した時に実行されるイベント
	// ------------------------------------------------------------
	xhr.onload = function(){

		// ------------------------------------------------------------
		// 受信した x-user-defined 文字列を取得する
		// ------------------------------------------------------------
		var binary = xhr.responseText;

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

			var data_url = "data:" + xhr.getResponseHeader("Content-Type") + ";base64," + base64;

			// 出力テスト
			console.log(data_url);

		});

	};


	// ------------------------------------------------------------
	// HTTP メソッドを指定、アクセス先を指定
	// ------------------------------------------------------------
	xhr.open("GET","https://hakuhin.jp/graphic/title.png");

	// ------------------------------------------------------------
	// コンテンツタイプのオーバーライド設定
	// ------------------------------------------------------------
	xhr.overrideMimeType("text/plain; charset=x-user-defined");

	// ------------------------------------------------------------
	// 送信データを指定し、通信を開始する
	// ------------------------------------------------------------
	xhr.send(null);

}else{

	// ------------------------------------------------------------
	// GM_xmlhttpRequest 関数を使用する(Greasemonkey スクリプトの場合)
	// ------------------------------------------------------------
	GM_xmlhttpRequest({
		method: "GET",
		url: "https://hakuhin.jp/graphic/title.png",
		overrideMimeType: "text/plain; charset=x-user-defined",
		onload: function (r){

			// ------------------------------------------------------------
			// レスポンスヘッダ文字列をオブジェクトに変換
			// ------------------------------------------------------------
			var headers = ResponseHeadersParseObject(r.responseHeaders);

			// ------------------------------------------------------------
			// 受信した x-user-defined 文字列を取得する
			// ------------------------------------------------------------
			var binary = r.responseText;

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

				var data_url = "data:" + headers["Content-Type"] + ";base64," + base64;

				// 出力テスト
				console.log(data_url);

			});
		}
	});
}
 



任意のバイナリのダウンロードを開始する

 
 


■任意のバイナリのダウンロードを開始する


アンカーの download プロパティについては、こちらで解説しています。
 
■動作方法
 
まず、document.createElement() メソッドを使って、HTMLAnchorElement オブジェクトを作成します。
 
引数に、"a" を指定します。
 
href プロパティに、Data URI Scheme 形式で、ダウンロードするファイルを指定します。
 
download プロパティに、デフォルトのファイル名を指定します。
 
HTMLAnchorElement オブジェクトを、任意のノードリストに登録します。
 
最後に、click() メソッドを実行します。
 
■動作例
 
任意の Blob オブジェクトのダウンロードを開始する

// ------------------------------------------------------------
// Blob オブジェクトを作成(UTF-8 形式のプレーンテキスト)
// ------------------------------------------------------------
var blob = new Blob(["保存テスト"] , {type:"text/plain"});

// ------------------------------------------------------------
// FileReader オブジェクトを生成
// ------------------------------------------------------------
var file_reader = new FileReader();

// ------------------------------------------------------------
// 読み込み成功時に実行されるイベント
// ------------------------------------------------------------
file_reader.onload = function(e){

	// ------------------------------------------------------------
	// HTMLAnchorElement オブジェクトを作成する
	// ------------------------------------------------------------
	var anchor = document.createElement("a");

	// ターゲットを設定
	anchor.target = "_blank";

	// ダウンロードするファイルを Data URI Scheme 文字列で指定
	anchor.href = file_reader.result;

	// デフォルトのファイル名を指定
	anchor.download = "mystring.txt";

	// ------------------------------------------------------------
	// ダウンロードを開始する
	// ------------------------------------------------------------
	document.body.appendChild(anchor);
	anchor.click();
	anchor.parentNode.removeChild(anchor);

};

// ------------------------------------------------------------
// 読み込みを開始する(Data URI Scheme 文字列を得る)
// ------------------------------------------------------------
file_reader.readAsDataURL(blob);
 
任意の ArrayBuffer オブジェクトのダウンロードを開始する

// ------------------------------------------------------------
// 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 += dic[(b >> 2)];
			n = (b & 0x03) << 4;
			i ++;
			if(i >= num) break;

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

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

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

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

	setTimeout(f,1);
}


// ------------------------------------------------------------
// コンテンツタイプ
// ------------------------------------------------------------
var content_type = "text/plain";

// ------------------------------------------------------------
// ArrayBuffer オブジェクトを作成
// ------------------------------------------------------------
// Uint8Array オブジェクトを作成
var ary_u8 = new Uint8Array([0xe4,0xbf,0x9d , 0xe5,0xad,0x98 , 0xe3,0x83,0x86 , 0xe3,0x82,0xb9 , 0xe3,0x83,0x88]);

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

// ------------------------------------------------------------
// ArrayBuffer から Base64 文字列に変換する (非同期実行)
// ------------------------------------------------------------
Base64_From_ArrayBuffer_Async(array_buffer,function(base64){

	// ------------------------------------------------------------
	// HTMLAnchorElement オブジェクトを作成する
	// ------------------------------------------------------------
	var anchor = document.createElement("a");

	// ターゲットを設定
	anchor.target = "_blank";

	// ダウンロードするファイルを Data URI Scheme 文字列で指定
	anchor.href = "data:" + content_type + ";base64," + base64;

	// デフォルトのファイル名を指定
	anchor.download = "mystring.txt";

	// ------------------------------------------------------------
	// ダウンロードを開始する
	// ------------------------------------------------------------
	document.body.appendChild(anchor);
	anchor.click();
	anchor.parentNode.removeChild(anchor);


});