JavaScriptでサーバーにバイナリデータを送信したい場合・・・
- XMLHttpRequest から送信
- あるいは Ajax から送信
- PHP側でそれを受け取る
みたいな方法が使えます。
ただその送信方法が分からず、意外と苦戦してしまいました。
そこで自分へのメモも兼ね、
ここでは JavaScriptでバイナリデータを送信してPHPで受信する方法 を詳解!
やり方さえ分かってれば、バイナリの送受信も怖くはありません。
このページの目次
1.まずはJS側でバイナリ送信するやり方
まずはブラウザ側(JavaScript側)からバイナリ送信するやり方。
その方法は主に次の2つ
- XMLHttpRequest を使う方法
- Ajax を使って送る方法
Ajaxだとバイナリは送れないと思っている人は多いですが、実は正しい Content-Type を指定してあげれば Ajaxからでも送信可能です。
それぞれの方法とコード例は以下の通り
XMLHttpRequestでバイナリデータ送信
例えばこういうバイト配列を送信したいとしましょう。
1 2 |
/// 送信したい元のバイト配列 var bytesData = [31, 139, 8, 0, 202, 160, 204, 93, 0, 255]; |
画像とか音声とか、、、そういうイメージですね。
そして XMLHttpRequest を使ってバイナリ送信する場合、
次みたいなコードでサーバー側に送信可能です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
/// 送信したい元のバイト配列 var bytesData = [31, 139, 8, 0, 202, 160, 204, 93, 0, 255]; var xhr = new XMLHttpRequest(); xhr.open('POST', 'http://example/hoge.php'); xhr.onload = function(e){ if (xhr.readyState === 4) { if (xhr.status === 200) { console.log(xhr.responseText); } else { console.error(xhr.statusText); } } }; xhr.setRequestHeader('Content-Type', 'application/octet-stream'); xhr.send(bytesData); |
大事なポイントは次の2つ
- ヘッダーに Content-Type を指定
バイナリ送信する場合は 'application/octet-stream' を追加するのを忘れずに!
- バイナリデータは send メソッドから指定
上コードのように xhr.send(byetsData); みたいに渡せばOK
こうすれば サーバー側でバイナリデータを直に受け取れます。
Ajaxからバイナリデータ送信するコード例
今のが XMLHttpRequest からバイナリ送信する例
お次は Ajax からバイナリデータ送信するコード例です。
▼ そのコード例というのがコチラ!
1 2 3 4 5 6 7 8 9 10 11 12 13 |
/// 送信したい元のバイト配列 var bytesData = [31, 139, 8, 0, 202, 160, 204, 93, 0, 255]; $.ajax({ url: 'http://example.com/receive_bin.php', type: 'POST', contentType: 'application/octet-stream', data: bytesData , processData: false, success: function(data, dataType){ console.log('response : ', data); } }); |
こちらも contentType に気を付けさえすればOK。
必ず 'application/octet-stream' を渡しておくのが肝ですね。
またデータ部分には data: bytesData みたく、そのままバイト配列を渡すだけです。
2.PHPからバイナリデータを受信する
そしてここからが肝心なところ
バイナリデータをJavaScriptから送信する方法が分かっても、、、
「PHPとかのサーバーサイドでどうやって受けとるのか」
それが僕自身よく分かっていませんでした。
でもやり方は簡単で、次のようなコードを書くだけ
1 2 |
/// 送信されたバイナリデータを受け取る $bindata = file_get_contents('php://input'); |
上コードの 'php://input' がポイント
これはリファレンスだと、こう説明されています。
php://input は読み込み専用のストリームで、 リクエストの body 部から生のデータを読み込むことができます。 POST リクエストの場合は $HTTP_RAW_POST_DATA よりも php://input を使うのが望ましいでしょう。php.ini ディレクティブの設定に依存しないからです。 さらに、$HTTP_RAW_POST_DATA がデフォルトで設定されない場合は、 always_populate_raw_post_data を有効にするよりも $HTTP_RAW_POST_DATA を使うほうがメモリの消費量が少なくなるでしょう。 php://input は、 enctype="multipart/form-data" に対しては使用できません。
引用元 : https://www.php.net/manual/ja/wrappers.php.php
通常のPOST送信だと、ポスト変数は $_POST から参照できます。
でも今回みたいにバイナリデータを直接送る場合、
この
'php://input' からデータ取得ができるという仕組みです。
そこで実際に、簡単なコードを書いてみました。
▼ バイナリ取得し、 var_export で整形して表示するコード
1 2 3 4 5 6 7 |
/// まずは生のバイナリデータを取得 $raw_data = file_get_contents('php://input') /// それを符号なしchar型の配列に変換 $unpacked = unpack('C*', $raw_data); var_export(unpacked); |
このコードの unpack関数 は生のバイナリデータを配列に展開できる関数
▼ unpack関数のリファレンス
今回は 'C*' , を指定してるので、次みたいな感じで展開されます。
1 2 3 4 5 6 7 8 9 10 11 |
array ( 1 => 31, 2 => 139, 3 => 8, 4 => 0, 5 => 202, 6 => 160, 7 => 204, 8 => 93, 9 => 0 ) |
ちゃんとJS側から送信したのが受け取れてます。
ここまでのまとめ
JS側で送信するときは Content-type に気を付け、
PHP側ではデータ受信に php://input を参照するのが大事なポイントかもしれません。
もし情報が間違ってるなどの場合はコメント欄からご指摘ください。
以上、JS&PHPでのバイナリ送受信のやり方でした。ではまた