Webアプリケーションのサーバ通信

通常のリンクやForm要素のactionとは異なり、ページ遷移を伴わないでサーバとの通信を行う方法です。

要は、30年以上前に流行った3階層クライアント・サーバシステムを、Web系のなんやかんやで実現するための基本となる機能の一つです。

このコンテンツの初版は2003年で、あまり内容に変更がなかった改訂版も2007年と、いつの間にか10年以上ほったらかしになっていました。

当然のこのながら今読み返すと『なんじゃこりゃ?』という内容なので、再度改訂版を作成することにしました。

以前の古いコンテンツです。IE3とかをサポートしなくてはいけない場合には、参考にしてください。SOAPとか言ってますねえ。笑っちゃいます (^ ^;

はじめに

このコンテンツで紹介する内容は、古いWebブラウザに関しては、一切考慮していません。

サンプルコードも、2019/1現在の最新のWebブラウザでのみ実行できます。

XMLHttpRequest

ページ遷移を伴わないでサーバとの通信を行う機能の代表格ですが、今時当たり前すぎる機能なので、通信処理だけではなく、Formの内容をサーバに送信したり、ついでにファイルをプレビューしてアップロードする方法なども紹介します。

実は新しい機能ではなく、1999年公開のInternet Explorer 5.0で実装された機能です(はっきり覚えていませんが、Internet Explorer 4.0でも使えた様な気もします)。

当時から充分に使える機能でしたが、何故かあまり話題にはなりませんでした。

単純にリクエストを投げてレスポンスを受けるだけであれば、非常に簡単に実装できます。

Getメソッドで、同期通信を行う

Getメソッドで同期通信を行うサンプルコードです。

URLを引数にして呼び出すと、レスポンスされた文字列を返します。

但し、メインスレッドでの同期通信は奨励されていません。

Getメソッドによる同期通信

Getメソッドで、非同期通信を行う

Getメソッドで非同期通信を行うサンプルコードです。

URLを引数にして呼び出すと、レスポンスされた文字列をダイアログに表示します。

Getメソッドによる非同期通信

Postメソッドで、非同期通信を行う

Postメソッドで非同期通信を行うサンプルコードです。

URLを引数にして呼び出すと、レスポンスされた文字列をダイアログに表示します。

Postメソッドによる非同期通信

7行目で、リクエストヘッダにContent-Typeを設定しています。

a=b&c=d形式に編集したテキストを送信する場合、application/x-www-form-urlencodedを設定する必要があります。

Postメソッドで、Formの内容を簡単に送信する

少し前までは、『(3) Postメソッドで、非同期通信を行う』のように、送信する内容をa=b&c=d形式に編集しなければいけませんでした。

しかし、最近はFormDataを使うことで、簡単にFormの内容をサーバに通信することができるようになりました。

FormDataによるFormの送信

3行目4行目でFormDataの内容を、キーと値を渡して編集しています。

マルチバイト文字も、内部でURLエンコードしてくれるので、そのまま設定することができます。

この例では固定文言ですが、実際には画面の入力値などを取得して設定することになるでしょう。

前の例とは異なり、FormDataを直接sendメソッドに渡した場合は、Content-Typeの設定は不要です。

FORM要素からFormDataを作成する

従来のFORM要素を元に、FormDataを作成することも可能です。

form要素からFormDataを作成する

ファイルをアップロードする

ファイルのアップロードも、驚くほど簡単になりました。

最低限必要なHTML

ファイルをアップロードする際にどうしても必要な要素です。

レンダリングはWebブラウザそれぞれですが、通常はボタンが表示され、それをクリックするとファイル選択用のダイアログが表示されます。

ファイルのアップロード

1行目でtype="file"となっているinput要素を取得し、2行目で選択したファイルを取得します。

ファイルが未選択の場合は、3行目のimg_fileの内容がundefinedとなるので、実際のプロジェクトでは判定が必要となります。

あとは、FormDataでFormの内容を送信するケースと同じです。

ファイルをアップロードする時に、プレビューもする

プレビューは、昔実現できたのですが、すぐにセキュリティの問題でできなくなってしまいました。

しかし、最近はFileReaderによって、簡単にそして安全に実現できるようになりました。

プレビューに必要なHTML

ファイルのアップロードには、どうしてもtype="file"となっているinput要素が必要なのですが、決して出来の良いUIとは言えないので、1行目で非表示にしています。

ファイルを選択する為のボタンが非表示ですが、その代わりにonchangeイベントにハンドラを設定しています。

4行目からが、プレビューの領域です。プレビューのサイズは、高さを200ピクセル固定としています。

画像のプレビュー

プレビューボタンをクリックすると実行されるのがpreviewメソッドです。

実際に行っているのは、非表示としたtype="file"のinput要素のclickメソッドを呼び出しているだけです。

clickメソッドを呼び出すと、ファイル選択ダイアログが表示されるので、そこでファイルを選択すると、onchangeに指定されているpreviewFileメソッドが呼び出されます。

ファイル選択ダイアログでキャンセルすると、onchangeイベントは発火しないので、previewFileメソッドは呼び出されません。

6行目で選択されたファイルを取得します。onchangeイベントにより呼び出されているので、選択されていないケースを想定する必要はありません。

FileReaderのインスタンスを作成し、loadイベントにイベントハンドラを設定した後、選択したファイルを引数にreadAsDataURLメソッドを呼び出します。

ファイルの呼び出しは非同期で行われるので、完了した時点でプレビューイメージのsrc属性にロード結果をセットします。

実は、ロード結果(このサンプルではreader.result)の内容は、base64でエンコードされたファイルの内容です(readAsDataURLメソッドでロードすると、base64でエンコードされたDataURL形式になります)。

先頭には、“data:image/jpeg;base64,”(jpegの場合)が付与されています。

このため、単純にimg要素のsrc属性に設定するだけで、画像が表示されます。

プレビューだけであればサーバとの通信が必要ないので、以下にサンプルと同じものを用意しました。

プレビューボタンを押下して、画像を選択してください。プレビュー領域に画像が表示されます。

サーバへの通信などは行いませんので、ご安心ください。

Image preview...

プレビュー後は、『(6) ファイルをアップロードする』で紹介した方法でアップロードを行うこともできますが、プレビューしている内容がbase64でエンコードされた文字列であることを考えれば、その文字列をそのままアップロードすることも考えられます。

サイズ的には3分の1ほど大きくなりますが、HTMLにそのまま埋め込めるメリットは、それなりに大きいと思います。

DBに格納する際も、文字列として扱えるので、扱いやすいかもしれません。

バイナリデータを扱う

Webブラウザ上でイメージを表示する場合は、IMG要素にURLを指定して表示させます。

しかし、それではイメージファイルをロードするタイミングや、表示する順序を正確に制御することができません。

最近は、XMLHttpRequestでバイナリデータを容易に処理できるようになったので、イメージの表示をプログラムから制御することができるようになりました。

イメージのロードと表示

12行目で、レスポンスをblobで返すように指定します。

blobは、バイナリ・ラージ・オブジェクト(英: Binary Large Object)の略で、データベースなどでも使われる型です。

blobの操作には、FileReaderが必要なので、5行目でそのインスタンスを作成し、9行目でreadAsDataURLメソッドを使用してロードします。

ロードが完了したら、img要素のsrc属性にセットするだけで、画像が表示されます。

複数の画像をロードして、一定間隔で順に表示するサンプルです。最初の画像の表示までは、少し時間がかかるかもしれません。