Asial Blog

Recruit! Asialで一緒に働きませんか?

【HTML5】File APIを使って、投稿された画像を即時表示する方法【小ネタ】

カテゴリ :
フロントエンド(HTML5)
タグ :
Tech
JavaScript
HTML5
こんにちは、橋本です。
今回は小ネタを1つ紹介したいと思います。 画像投稿フォームを作る際に、投稿された画像を即時表示したいなんてことありませんか? そんなときに便利なのが、HTML5で追加されたFile API。

File APIを使えば、投稿された画像(正確には、選択されたローカルファイル)の情報を取得することができます。

では、画像投稿機能のサンプルを元に、File APIの使い方を見て行きましょう。
File API自体はjQueryと何の関係もありませんが、いろいろと面倒なので今回もjQueryを使っています。

サンプル
  1. <!DOCTYPE HTML>
  2. <html lang="ja">
  3.     <head>
  4.         <meta charset="UTF-8">
  5.         <script src="http://code.jquery.com/jquery-latest.js" type="text/javascript"></script>
  6.         <title>サンプル</title>
  7.     </head>
  8.     <body>
  9.         <input class="fileInput" type="file" /><br>
  10.         <img src="" alt="" />
  11.         <script>
  12.             $('.fileInput').change(function(){
  13.                 // 1. 選択されたファイルがない場合は何もせずにreturn
  14.                 if (!this.files.length) {
  15.                     return;
  16.                 }
  17.  
  18.                 var file = this.files[0],            // 2. files配列にファイルが入っています
  19.                     $_img = $(this).siblings('img'), // 3. jQueryのsiblingsメソッドで兄弟のimgを取得
  20.                     fileReader = new FileReader();   // 4. ファイルを読み込むFileReaderオブジェクト
  21.  
  22.                 // 5. 読み込みが完了した際のイベントハンドラ。imgのsrcにデータをセット
  23.                 fileReader.onload = function(event) {
  24.                     // 読み込んだデータをimgに設定
  25.                     $_img.attr('src', event.target.result);
  26.                 };
  27.  
  28.                 // 6. 画像読み込み
  29.                 fileReader.readAsDataURL(file);
  30.             });
  31.         </script>
  32.     </body>
  33. </html>

サンプルのコメントに番号をふっておいたので、番号に沿って説明していきたいと思います。

まず1ですが、ファイルの情報は、input要素のfiles配列にFileオブジェクトとして格納されています。
ですので、input要素のfiles配列のlengthでファイルの選択の有無を確認し、選択されていない場合には処理を終えるよう設定しています。


2は上記で説明したとおり、files配列にファイルが格納されていますので、そこから0番目の要素としてファイルを取得しています。


3は取得したファイルのデータを設定するimgタグを予め変数に格納しています。jQueryオブジェクトだということを明示するために、"$_"プレフィクスをつけています。


4はファイルを読み込むためのFileReaderオブジェクトをインスタンス化し、変数に入れています。これが今回のキモです。

FileReaderオブジェクトはファイルを読み込むためのオブジェクトです。
各種メソッドにFileオブジェクトを渡すことで、非同期でデータの読み込みを行います。
以下の4つのメソッドがあるのですが、よく使うのは最初の2つです。画像に関しては最初の1つでいいと思います。

readAsDataURL(file); // Data URLスキームの形式で読み出す
readAsText(file, encoding); // テキストとして読み出す。エンコーディングを指定可。
readAsBinaryString(file); // バイナリデータとして読みだす。
readAsArrayBuffer(file); // ArrayBufferを返す。詳細不明

5はFileReaderオブジェクトのonloadイベントのイベントハンドラを設定しています。
上記でちょっと触れたんですが、FileReaderオブジェクトのファイルの読み出しは非同期となりますので、イベントハンドラを設定する必要があります。

6でデータの読み込みを開始しています。今回は取得したデータをそのままimgタグのsrcにつっこむので、readAsDataURLメソッドを使用しています。


どうでしょう。非常に簡単ですね。
このサンプルをちょこっといじることで、選択されたファイルをajaxを使って即時サーバに送って保存するといったことも可能になります。

  1. <!DOCTYPE HTML>
  2. <html lang="ja">
  3.     <head>
  4.         <meta charset="UTF-8">
  5.         <script src="http://code.jquery.com/jquery-latest.js" type="text/javascript"></script>
  6.         <title>サンプル</title>
  7.     </head>
  8.     <body>
  9.         <input class="fileInput" type="file" /><br>
  10.         <img src="" alt="" />
  11.         <script>
  12.             $('.fileInput').change(function(){
  13.                 // 1. 選択されたファイルがない場合は何もせずにreturn
  14.                 if (!this.files.length) {
  15.                     return;
  16.                 }
  17.  
  18.                 var file = this.files[0],            // 2. files配列にファイルが入っています
  19.                     $_img = $(this).siblings('img'), // 3. jQueryのsiblingsメソッドで兄弟のimgを取得
  20.                     fileReader = new FileReader();   // 4. ファイルを読み込むFileReaderオブジェクト
  21.  
  22.                 // 5. 読み込みが完了した際のイベントハンドラ。サーバにデータを送信
  23.                 fileReader.onload = function(event) {
  24.                     $.ajax({
  25.                         type: 'POST',
  26.                         url: 'http://fairuwookurusa-ba.com',
  27.                         data: {file: event.target.result},
  28.                         success: function(){
  29.                             $_img.attr('src', event.target.result);
  30.                         },
  31.                         error: function(a, b, c){
  32.                             alert('ファイルのアップロードに失敗しました');
  33.                             console.log(a, b, c);
  34.                         }
  35.                     });
  36.                 };
  37.  
  38.                 // 6. 画像読み込み
  39.                 fileReader.readAsDataURL(file);
  40.             });
  41.         </script>
  42.     </body>
  43. </html>


またまた簡単ですね。サーバに送る際には、readAsBinaryStringメソッドを使って、バイナリとして取得してもいいかもしれませんね。

以上、簡単な小ネタの紹介でした。