JavaScript typed arrays を使ったバイナリデータの受信
XMLHttpRequest オブジェクトの r
esponseType
プロパティをセットすると、サーバに期待する response type を変更する事が出来ます。設定可能な値は空文字列(デフォルト), "arraybuffer"
, "blob"
, "document"
, "json"
, そして "text"
です。response
プロパティには responseType
に応じてArrayBuffer
, Blob
, Document
, JSON
, または string のエンティティボディが入ります。リクエストが不完全であったり成功しなかった場合は null
になります。
このサンプルでは画像をバイナリファイルとして読み込み、生のバイト列から 8 ビット符号なし整数値の配列を作成します。
var oReq = new XMLHttpRequest(); oReq.open("GET", "/myfile.png", true); oReq.responseType = "arraybuffer"; oReq.onload = function (oEvent) { var arrayBuffer = oReq.response; // Note: not oReq.responseText if (arrayBuffer) { var byteArray = new Uint8Array(arrayBuffer); for (var i = 0; i < byteArray.byteLength; i++) { // do something with each byte in the array } } }; oReq.send(null);
上記の方法の代わりに Blob
インタフェースを利用して arraybuffer データから直接 Blob
を 構築 (construct) します。
var oReq = new XMLHttpRequest(); oReq.open("GET", "/myfile.png", true); oReq.responseType = "arraybuffer"; oReq.onload = function(oEvent) { var blob = new Blob([oReq.response], {type: "image/png"}); // ... }; oReq.send();
更に、responseType
プロパティに "blob"
文字列をセットする事で、 Blob
としてバイナリファイルを読む事も出来ます。
var oReq = new XMLHttpRequest(); oReq.open("GET", "/myfile.png", true); oReq.responseType = "blob"; oReq.onload = function(oEvent) { var blob = oReq.response; // ... }; oReq.send();
古いブラウザでのバイナリデータの受信
下に示す load_binary_resource()
関数は指定した URL からロードしたバイナリデータを関数の呼び元 (caller)に返します。
function load_binary_resource(url) { var req = new XMLHttpRequest(); req.open('GET', url, false); //XHR binary charset opt by Marcus Granado 2006 [https://mgran.blogspot.com] req.overrideMimeType('text\/plain; charset=x-user-defined'); req.send(null); if (req.status != 200) return ''; return req.responseText; }
魔法が 5 行目にかかっていて、 MIME type を上書きする事で user-defined 文字セット のプレインテキストとして扱う事をブラウザに強制します。これによりブラウザはパースせずバイト列を未処理のまま通します。
var filestream = load_binary_resource(url); var abyte = filestream.charCodeAt(x) & 0xff; // throw away high-order byte (f7)
上記のサンプルでは、ロードしたバイナリデータ内のオフセット x のバイトを取得します。 x
の有効範囲は 0
から filestream.length-1
です。
詳細な説明は downloading binary streams with XMLHttpRequest を見て下さい。また downloading files も見て下さい。
バイナリデータの送信
XMLHttpRequest の send
メソッドは拡張され、 ArrayBuffer
, Blob
, または File
オブジェクトを受け付ける事でバイナリデータの送信が容易になりました.
続くサンプルはその場 (on-the-fly)で作ったテキストファイルを POST
メソッドで "file" をサーバに送信します。このサンプルはプレインテキストを使っていますが、代わりにデータがバイナリファイルだとイメージする事も出来ます。
var oReq = new XMLHttpRequest(); oReq.open("POST", url, true); oReq.onload = function (oEvent) { // Uploaded. }; var blob = new Blob(['abc123'], {type: 'text/plain'}); oReq.send(blob);
バイナリデータとして typed arrays を送信
同等にバイナリデータとして JavaScript typed arrays を送信する事も出来ます。
var myArray = new ArrayBuffer(512); var longInt8View = new Uint8Array(myArray); for (var i=0; i< longInt8View.length; i++) { longInt8View[i] = i % 255; } var xhr = new XMLHttpRequest; xhr.open("POST", url, false); xhr.send(myArray);
これは 8ビット整数の 512 バイトの配列を構築して送信します。勿論、好きな任意のバイナリデータで使えます。
ArrayBuffer
オブジェクトの送信サポートは Gecko 9.0 (Firefox 9.0 / Thunderbird 9.0 / SeaMonkey 2.6)で追加されました。他のブラウザのサポート情報をここに追記して下さい。フォーム送信とファイルアップロード
この節をお読み下さい。
Firefox 独自のサンプル
このサンプルでは非同期にバイナリコンテンツを送信するのに POST
メソッドと Firefox にある非標準の sendAsBinary()
を使います。
var req = new XMLHttpRequest(); req.open("POST", url, true); // set headers and mime-type appropriately req.setRequestHeader("Content-Length", 741); req.sendAsBinary(aBody);
4行目で Content-Length ヘッダに 741 をセットするのは、データが 741 バイト長である事を示します。送信データの実際のサイズに応じてこの値を変更する必要があります。
5行目では sendAsBinary()
メソッドを使ってリクエストをはじめます。
また、nsIFileInputStream
のインスタンスの send()
を通す事でバイナリコンテンツを送信できます。この場合は、あなた自身が Content-Length
ヘッダセットしてはならず、この情報はストリームから自動的に取得されます:
// Make a stream from a file. var stream = Components.classes["@mozilla.org/network/file-input-stream;1"] .createInstance(Components.interfaces.nsIFileInputStream); stream.init(file, 0x04 | 0x08, 0644, 0x04); // file is an nsIFile instance // Try to determine the MIME type of the file var mimeType = "text\/plain"; try { var mimeService = Components.classes["@mozilla.org/mime;1"] .getService(Components.interfaces.nsIMIMEService); mimeType = mimeService.getTypeFromFile(file); // file is an nsIFile instance } catch (oEvent) { /* eat it; just use text/plain */ } // Send var req = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"] .createInstance(Components.interfaces.nsIXMLHttpRequest); req.open('PUT', url, false); /* synchronous! */ req.setRequestHeader('Content-Type', mimeType); req.send(stream);