バイナリデータの送信と受信

by 1 contributor:

JavaScript typed arrays を使ったバイナリデータの受信

XMLHttpRequest オブジェクトの responseType プロパティをセットすると、サーバに期待する 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 [http://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 バイトの配列を構築して送信します。勿論、好きな任意のバイナリデータで使えます。

注記: XMLHttpRequest を使った 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);

ドキュメントのタグと貢献者

Contributors to this page: yoya
最終更新者: yoya,