http経由でライブラリ読み込み2007年04月24日 21時04分28秒

XHRとADODB.Streamを組み合わせる

http経由でソースを取得するのはXHRで問題ないが、日本語のコメントが入ったeucエンコードのソースなんかだとちょっとアレなので、ADODB.Streamと組み合わせてみたり。まあ、定番テクニックですか。

基本的には以下の流れになる。

  1. XHR(Microsoft.XMLHTTP)でソースを取得
  2. バイナリモードで開いたADODB.StreamにXHR.responseBodyを書き込む
  3. ADODB.Streamを巻き戻し、テキストモードに変更する
  4. Charsetプロパティに"_autodetect"を指定して自動検出にする
  5. ReadText()でテキスト読み出しをする
具体的なコードは以下のようになる。(前のエントリのgetSource()のみ変更)
getSource : function(url) {
	var stream = new ActiveXObject("ADODB.Stream");
	var xhr = new ActiveXObject("Microsoft.XMLHTTP");
	try {
		xhr.open( "GET", url, false );
		xhr.send();
		
		stream.Open();
		stream.Type = 1; // バイナリモード
		stream.Write( xhr.responseBody ); // バイナリ書き込み
		
		stream.Position = 0; // 読み取り位置を巻き戻す
		stream.Type = 2; // テキストモードに変更
		stream.Charset = "_autodetect"; // 文字コード自動検出
		
		return stream.ReadText();
	} finally {
		stream.Close();
	}
}
ちょっと注意点があって、
  • 先にTypeを変更してからPositionを変更する
  • Typeを変更する前にCharsetを割り当てる
といった操作を行うと、「このコンテキストで操作は許可されていません」と怒られるので、かならずPosition = 0 → Type = 2 → Charset = charsetの順序で実行する必要がある。

コードサンプル

ローカルでwebサーバが動いていて、ルート直下にdummy.jsとprototype.jsがある場合

with( {
	// ライブラリのパスリスト
	libs : [
		"http://localhost/dummy.js",
		"http://localhost/prototype.js"
	],
	// libs[]のインデックス
	index : 0,
	// ソース取得メソッド
	getSource : function(url) {
		var stream = new ActiveXObject("ADODB.Stream");
		var xhr = new ActiveXObject("Microsoft.XMLHTTP");
		try {
			xhr.open( "GET", url, false );
			xhr.send();
			
			stream.Open();
			stream.Type = 1; // バイナリモード
			stream.Write( xhr.responseBody ); // バイナリ書き込み
			
			// ↓ 最初のPOST時に順序が間違ってたので修正(07.04.25 02:07)
			stream.Position = 0; // 読み取り位置を巻き戻す
			stream.Type = 2; // テキストモードに変更
			stream.Charset = "_autodetect"; // 文字コード自動検出
			
			return stream.ReadText();
		} finally {
			stream.Close();
		}
	}
} ) {
	while( index < libs.length ) {
		try {
			eval( getSource( libs[ index++ ] ) );
		} catch(e) {
			WScript.Echo( e.description || e.message || "error" );
		}
	}
}

WScript.Echo( $R(1, 10).inject( 0, function(total, value) {
	return ( total + value );
} ) ); // → 55
ちなみにlibsの各要素で「file://ファイルへの絶対パス」を使用するとローカルファイル読み出しができる。getSource()内でパラメータを検査して判断すればURLでもファイルパスでも対応できるようになる。

蛇足

せっかくADODB.Streamでエンコードの判別を行ってるけど、_autodetect時はutf-8をうまく判別してくれないのよね...

コメント

コメントをどうぞ

※メールアドレスとURLの入力は必須ではありません。 入力されたメールアドレスは記事に反映されず、ブログの管理者のみが参照できます。

※なお、送られたコメントはブログの管理者が確認するまで公開されません。

名前:
メールアドレス:
URL:
コメント:

トラックバック

このエントリのトラックバックURL: http://dara-j.asablo.jp/blog/2007/04/24/1463770/tb

※なお、送られたトラックバックはブログの管理者が確認するまで公開されません。