そろそろ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関数です。