[Javascript] FileAPIの使い方サンプルソース

ブラウザを使ったWebアプリケーションで、ローカルファイルをサーバーにアップロードせずに、読み取ることで、いろいろなエディタアプリなどが作れます。 そんな時に必須なJavascriptのFileAPIという技術のサンプルを掲載します。

ソースコード

index.html

<meta charset='utf-8'/> <link rel='stylesheet' href='style.css'/> <script src='main.js'></script> <input type="file" name="file" style="display:none;"> <button type="button" name="file_access">ファイル選択</button> <div class='response'></div>

style.css

.response > *{ border:1px dotted #aaa; padding:10px; max-width:200px; margin:10px; } .response img{ max-width:100%; }

main.js

(()=>{ // ページ読み込み後に処理を開始する switch(document.readyState){ case 'complete': case 'interactive': new Main() break default: window.addEventListener('DOMContentLoaded', (()=> new Main())) break } // メイン処理 function Main(){ this.init() this.set_event() } // 初期設定 Main.prototype.init = function(){ this.button = document.querySelector(`button[name='file_access']`) this.input = document.querySelector(`input[type='file']`) this.response = document.querySelector(`div.response`) } // イベント設定 Main.prototype.set_event = function(){ this.button.addEventListener('click' , this.click_button.bind(this)) this.input.addEventListener('change' , this.access_file.bind(this)) } // ボタンが押された処理 Main.prototype.click_button = function(){ this.input.click() } // ファイルアクセス処理 Main.prototype.access_file = function(e){ const files = e.target.files for(const file of files){ if(!file.type){continue} const reader = new FileReader() const types = file.type.split('/') if(!types[0]){continue} switch(types[0]){ case 'text': reader.readAsText(file) reader.onload = (function(e){this.view_text(e.target.result)}).bind(this) break default: reader.readAsDataURL(file) reader.onload = (function(types,e){this.view_data(e.target , types)}).bind(this , types) break } } } // 取得したファイルの表示 Main.prototype.view_data = function(reader, types){ switch(types[0]){ case 'image': this.view_image(reader.result) break case 'video': this.view_video(reader) break case 'audio': this.view_audio(reader) break } } // テキストの表示 Main.prototype.view_text = function(text){ const div = document.createElement('div') div.textContent = text this.response.appendChild(div) } // 画像の表示 Main.prototype.view_image = function(data){ const img = document.createElement('img') img.src = data this.response.appendChild(img) } // 動画の表示 Main.prototype.view_video = function(data){ const video = document.createElement('video') video.src = data this.response.appendChild(video) } // 音声の表示 Main.prototype.view_audio = function(data){ const audio = document.createElement('audio') audio.src = data this.response.appendChild(audio) } })()

デモ

ボタンを押して、パソコン内のファイルを選択してみてください。 ファイルの中身が、下記に表示されます。

解説

1. htmlで重要なのは、type=fule

inputタグのtype=fileで指定されたファイルに、javascriptのFileAPIはアクセスが簡単にできるようになります。

2. changeイベントで用意にファイルアクセス

inputタグにchangeイベントをセットすると、ファイルが選択された時に、access_file()というMainの子関数が実行されます。 この時に、受け取った引数(e)の、targetに入っている、filesという中身が、ファイル一覧の配列になっています。 inputタグに、multiple属性を付けると、複数のファイルが選択できるようになります。(今回のソースでも複数ファイルに対応しています。) ※1個の場合でも配列です。

3. テキストファイルと、それ以外の画像や動画などのバイナリファイルで、読み込み方式を返る

データを読み込む、FileReader()というインスタンスで、実際のファイルにアクセスしてデータを読み取ります。 テキストファイルは受け取った後のデータが、ファイルの中身のテキストになってくれますが、バイナリファイルは、base64形式で受け取れるデータとして読み込むようにしています。 テキストの場合は、 const reader = new FileReader() reader.readAsText(file) バイナリの場合は、 const reader = new FileReader() reader.readAsDataURL(file) これで受け取った後の操作が楽になります。

4. 受け取った後は、表示に繋げるだけ

テキストの場合は、文字列として表示すれば良いんですが、htmlファイルの場合は、innerHTMLとして実行すると、HTMLタグとして表示することができます。 (今回はこの対応はしていません、) バイナリファイルは、タイプに応じて、画像、動画、音声のそれぞれのタグを分けてますが、他にも対応させたいタイプがあれば、独自に書くと自由に対応することができます。