そろそろHTML5 APIのひとつでもリファレンスしていこうかな・・・
かといって今さらcanvasとかやってもしょうがないし、MathML
みたいなマニアックなものは覚えても使う機会があるかどうか・・・という事で
『File API
』というヤツを手始めに覚えようかと思います。
HTML5以前はブラウザ(またはWebアプリ)からローカルファイルを扱うには<input type="file">
タグを利用してユーザーがファイルをアップロードする必要がありましたが、
File APIの登場でJavaScriptからローカルファイルを直接読み取ることができる様になりました。
このAPIはユーザーが指定したローカルファイル(Webブラウザが動作するパソコンのHDDやSSDといったストレージに置かれたファイル)の情報やデータを取得できます。
File APIにはローカルファイルの読み取りだけでなく、書き込みやファイルを操作するAPIも用意されています。
ディレクトリ階層内にフォルダやファイルの作成・保存を行うAPI
書き込み・保存ができる様になったといっても、File APIでアクセスできるのはあくまでユーザーが指定したファイルだけになります。
セキュリティの問題上でパスを「C:\file.txt
」や「../text/file.txt
」の様に指定して動的に読み込み元ファイルを書き直す事はできません。
ブラウザ | 対応バージョン |
---|---|
Internet Explorer | 10.0 |
Fire Fox | 3.6以降 |
Chrome | 6.0以降 |
Safari | 5.1以降 |
Opera | 11.1以降 |
まぁまず各主要ブラウザの最新版を使っていれば問題無く実装されている様です。
if(window.File && window.FileReader) { //File API alert("ご使用のブラウザはFile APIを実装しています"); }else{ alert("ご使用のブラウザはFile APIをサポートしていません"); }
一応こちらのテスト用スクリプトを使えば使用するブラウザがFile APIに対応しているかがわかります。
情報を取得するファイル選択は<input>
タグを使用します。
複数のファイルを選択できる様にmultiple
属性を用います。
<input id="loadFile" type="file" multiple>
function loadFile_changeHandler(e){ var files = e.target.files; var fileData = ""; for(var i = 0; i < files.length; i++){ var fileVal = files[i]; fileData += 'ファイル名:' + escape(fileVal.name) + '<br>' + 'ファイルサイズ:' + fileVal.size + ' バイト<br>' + 'MIMEタイプ:' + fileVal.type + '<br>' + '最終更新日時:' + fileVal.lastModifiedDate + '<hr>'; } $('#info').innerHTML = fileData; } function $(id) { return document.querySelector(id); }
これで指定したファイルの「ファイル名」、「ファイルサイズ」、「MIMEタイプ」、「最終更新日時」の各パラメーターが変数files
の配列内に格納されます。
こちらのデモページでローカルファイルを選択してください。
ローカルファイルの読み取りにはFile APIの『File Reader
』オブジェクトを利用します。
テキストファイルだけでなく、画像などのバイナリファイルも読み取りが可能です。
読み取りメソッド | 説明 |
---|---|
readAsBinaryString(File) | 非同期にファイルを読み取り バイナリ文字列を取得 |
readAsText(File, enc) | 非同期にファイルを読み取り、テキスト文字列を返します。 文字エンコーディングを指定する引数encを省略すると「UTF-8」として読み取ります |
readAsDataURL(File) | 非同期にファイルを読み取り、Data URIにエンコードされたデータを返します |
readAsArrayBuffer(File) | 非同期にファイルを読み取り、ArrayBufferオブジェクトとしてデータを返す |
<input id="loadFile" type="file" multiple><br> <textarea id="info"></textarea>
formタグにて画像のアップロードフォームを定義
$("#loadFile").onchange = function(evt){ var file = evt.target.files[0]; if(!file.type.match(/text/)){ alert('テキストファイルを' + '選んで下さい'); return; } var reader = new FileReader(); reader.onload = function(evt) { $("#info").value = evt.target.result; } reader.readAsText(file, "Shift_JIS"); } function $(id) { return document.querySelector(id); }
こちらのデモページでローカルのテキスト形式のファイルを選択してください。
onload
イベントが発生し、ファイル内容はonload
イベントのイベントハンドラ内で受け取ったデータはtarget.result
プロパティに格納されます。onchange
イベントが発生するので、このイベントを補足するためのイベントハンドラを指定します。target.files
プロパティにアクセスして、ファイル情報を調べます。FileReader
のオブジェクトを作成します。readAsText
メソッドを実行し、読み取りを開始します。onload
イベントが発生するので、onload
プロパティにイベントハンドラを登録しておきます。target.result
プロパティを参照して、読み取られたテキストを <textarea>
に表示します。readAsText
メソッドでは、第2引数に"Shift_JIS"を指定しているので、文字コードがShift_JISのテキストを正しく読み取ることができます。このメソッドは、テキストエンコーディングを自動判定できないので文字コードが合致していないと文字化けを起こします。FileReader
オブジェクトのreadAsDataURL
メソッドを使うと、ファイルを読み取り、URLエンコードされたデータを取得できます。
<form action="upload.php" method="post" enctype="multipart/form-data"> <input id="afile" type="file" name="img"><br> <img id="thumb" width="320"> <input id="up_btn" type="submit" value="アップロード" /> </form> //①
showImage(false); $("#afile").onchange = function(evt){ showImage(false); var files = evt.target.files; if(files.length == 0) return; var file = files[0]; if(!file.type.match(/image/)) { alert('画像ファイルを選んでください'); return; } //② var reader = new FileReader(); //③ reader.onload = function(evt) { $("#thumb").src = reader.result; showImage(true); } reader.readAsDataURL(file); } function showImage(b) { var val = b ? "block" : "none"; $("#up_btn").style.display = val; $("#thumb").style.display = val; } //④ function $(id) { return document.querySelector(id); }
選択した画像のファイルのサムネイルを表示させるデモがこちら
<form>
~</form>
ではPHPスクリプトの専用CGI「upload.php」へ画像ファイルをアップロードを想定し、画像のアップロードフォームを定義。onchange
イベントのために、onchange
プロパティにイベントハンドラを設定し、FileReader
オブジェクトのreadAsDataURL
メソッドを利用して画像ファイルを読み取ります。onload
イベントが発生するとresult
プロパティを参照することで読み取られたデータを取得できます。<img>
タグとアップロードを表示します。Filereader
オブジェクトのreadAsBinaryString
メソッドを利用したバイナリファイルの解析は
同メソッドで読み取ったデータはJavaScriptの文字列として取得できます。(1バイトが1文字のデータ)文字列なのでcharCodeAt
やcharAt
等の文字列が持つ各種メソッドを利用できます。
<input id="afile" type="file"><br> <div id="info"></div><br> <img id="thumb" width="320">
var targetfile = null; $("#afile").onchange = function(evt){ var files = evt.target.files; if(files.length == 0) return; targetFile = files[0]; var reader = new FileReader(); reader.onload = readPNGFile; reader.readAsBinaryString(targetFile); //① } //② function readPNGFile(evt) { var bin = evt.target.result; var sig = String.fromCharCode( 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a); //③、④ var head = bin.substr(0, 8); if(sig != head) { alert("PNGファイルではありません"); return; } var width = getBinValue(bin, 8 + 0x08, 4); var height = getBinValue(bin, 8 + 0x0c, 4); var depth = bin.charCodeAt(8 + 0x10); $("#info").innerHTML = "width: " + width + "px<br>" + "height: " + height + "px<br>" + "depth: " + depth + "bit"; var reader = new FileReader(); reader.onload = function(e) { $("#thumb").src = reader.result; } reader.readAsDataURL(targetFile) } //⑤ function getBinValue(bin, i, size) { var v = 0; for(var j= 0; j < size; j++){ var b = bin.charCodeAt(i + j); v = (v << 8) + b; } return v; } //⑥ function $(id) { return document.querySelector(id); }
選択されたPNGファイルをバイナリファイルを解析するデモがこちら
FileReader
オブジェクトのreadAsBinaryString
メソッドを利用します。onload
イベントでreadPNGFile
関数でPNGファイルの解析を行う。String.fromCharCode
メソッドを使うと、特定のバイトからなる文字列を作成できます。これを利用してPNGファイルのシグネチャ文字列を作成しています。String.substr
メソッドを利用すれば、文字列の一部を切り取ることができます。readAsDataURL
メソッドを利用してimgタグのsrc属性に読み取ったデータを設定します。getBinValue
関数です。