XMLHTTPRequestによるバイナリデータ取得(モダンブラウザ専用)
現在Web Audio APIを利用したアプリケーションを書いていますが、オーディオサンプルをロードするためにXMLHTTPRequest(以下XHR)を使って波形データをロードする処理が必要になったのでreminderをここに残しておきます。
XHRでテキストデータを受信する場合はjQueryのjQuery.ajax
を使うのが簡単で互換性も確保できます。しかしバイナリデータの場合はXHRを直接使う必要があります。
jQueryは今のところバイナリデータを扱うような作りにはなっていません(
jquery ajax バイナリデータ
などと検索してみて下さい)。
バイナリファイルの受信方法は次のMozillaドキュメントに解説があります。
Mozillaドキュメントの多くは和訳もあり、上記URLの
en-US
をja
に変えれば和訳ドキュメントを見ることができます。しかし今この文章を書いている時点ではまだ作業中で半分も日本語になってない状態です。
設定方法は2種類あります。
.overrideMimeType("text/plain; charset=x-user-defined")
(旧式).responseType = 'arraybuffer'
(新式)
今回はWeb Audio APIを使うことが前提なので新方式を使います。パターンは次のようになります(Mozillaドキュメントより抜粋)。
var oReq = new XMLHttpRequest(); oReq.onload = function(e) { var arraybuffer = oReq.response; // not responseText /* ... */ } oReq.open("GET", url, true); oReq.responseType = "arraybuffer"; oReq.send();
全体の流れを確認します。
- まずXHRオブジェクトを生成
- 送信前に設定(順不同)
.onload
に応答時のハンドラを設定(詳しくは後で...).open(メソッド, URL, true)
で相手先を設定- ちなみに最後がfalseだと結果が返るまでブロック(やってはいけない!)
.responseType
を'arraybuffer'に設定(今回はこれが一番のポイント)
.send()
で送信
responseType属性(送信用)とresponse属性(応答用)のリファレンスは次の通り。
- http://www.w3.org/TR/XMLHttpRequest/#the-responsetype-attribute
- http://www.w3.org/TR/XMLHttpRequest/#the-response-attribute
今回必要な部分だけ簡単にまとめます。
- 送信前に
.responseType
を'arraybuffer'にする- 応答時は
.response
にArrayBufferオブジェクトを返す - 失敗時(404など)でも空のArrayBufferを返すことに注意
- 応答時は
http://www.w3.org/TR/XMLHttpRequest/#arraybuffer-response-entity-body
応答処理用ハンドラはonloadに設定します。
.onload = function (event) { ... }
loadイベントの他にloadstart(開始時)、progress(処理中)、error(エラー発生)などがあります。全イベントの一覧は次の通りです。
http://www.w3.org/TR/XMLHttpRequest/#event-handlers
errorはサーバ応答がない場合などの処理用で、例えば404(not found)などは(サーバが応答しているので)loadで処理することに注意して下さい。
引数のeventはProgressEventで、progressイベント処理中に進行状況を取得するのに用います(それ以外にはあまり使い道なし)。
https://dvcs.w3.org/hg/progress/raw-file/tip/Overview.html#progressevent
.lengthComputable
HTTPレスポンスヘッダにContent-Length
があればtrue.loaded
実際に転送したサイズ.total
Content-Length
があればそのサイズ、なければ0
受信時の情報取得はXHRオブジェクトから行います。event.targetにXHRオブジェクトが渡されるのでそれを使っても同じです。
oReq.onload = function(event) { xhr = event.target; // 外側のoReqと同じオブジェクト if (xhr.status == 200) { // 成功時 var arraybuffer = xhr.response; // 受信したバイナリデータ // 以下成功時の処理(略) } else { // エラー処理の例(404の場合は"Cannot load (Not Found): URL"と表示) alert("Cannot load (" + xhr.statusText + "): " + xhr.responseURL); }