スタートページ >
Javascript >
File API
fileReader:ローカルファイルの内容表示
fileList ではファイルの属性を取り出すだけでしたが、fileReader では、それに加えて、ファイルの中身を取り出す機能をもっています。
ここでは、fileList 例2:ダイアログボックスによる属性の取得(this) に加える事項につき説明します。
fileReaderの主要機能は、ファイル読込みの状態監視(読込みエラー、読取状況の表示、読取正常完了など)ですが、正常完了以外のケースを作成するのが面倒なので、ここでは、正常完了することを前提にしています。
また、fileReader での読込方法を、ここでは、
readAsText:テキストファイル(文字データ)の読込み
readAsDataURL:画像ファイルの読込み
に限定しています。
選択されたファイルの全文を表示します。しかし、このプログラムでは次のような制約があります。
text/plain
ファイルの文字コードと、行Hでの文字コードが一致しないと文字化けします。
ここでは UTF-8 を標準にしているので Shift-JIS のファイルは文字化けします。
文字コードが一致していても、改行コードが無視されます。
text/html
表示ファイルで記述しているリンク先や画像のURLが相対指定だと、このページ(プログラムのあるページ)からの相対指定だとされ、正しく動作しません。
表示ファイルに、このページと同じstyleやscriptがあると、表示ファイルでの指定が優先され、このページの画面にまで影響してしまいます。
image/xxx
対象ファイルの画像サイズのままで表示される(縮小されない)ので、画面からはみ出してしまうことがあります。
上記以外のファイルは開けません。
<script>
function fileReader(files) { // 行A
for (var i = 0; i < files.length; i++){ // 行B
var ファイル = files[i]; // 行C
var ファイル名 = files[i].name;
var タイプ = files[i].type;
var サイズ = files[i].size;
document.getElementById("属性表示場所").innerHTML
= "ファイル名= " + ファイル名
+ ", タイプ = " + タイプ
+ ", サイズ = " + サイズ + "bytes";
var reader = new FileReader(); // 行D
if (タイプ.match('text.*') ) { // 行E テキストのとき
reader.onload = function(event) { // 行F
document.getElementById("内容表示場所").innerHTML
= event.target.result ; // 行G
}
reader.readAsText(ファイル, "utf-8"); // 行H
}
else if (タイプ.match('image.*') ) { // 行I 画像ファイルのとき
reader.onload = function(event) { // 行J
var tagDiv = document.createElement('div'); // 行K1 <div>
var tagImg = document.createElement('img'); // 行K2 <img>
tagImg.src = event.target.result; // 行K3 <img src=~>
tagDiv.appendChild(tagImg); // 行K4 <div><img src=~>
document.getElementById("内容表示場所").innerHTML
= tagDiv.innerHTML ; // 行K5
}
reader.readAsDataURL(ファイル); // 行L
}
else {
document.getElementById("内容表示場所").innerHTML
= "対象以外のタイプです。";
}
}
}
</script>
<input type="file" multiple <!-- 行M -->
onChange="fileReader(this.files)"></input></p>
<div id="属性表示場所" class="red">ここに属性が表示されます。</div>
<div id="内容表示場所">ここにファイル内容が表示されます。</div>
表示量が多いので、1ファイルごとにアラームを出して表示します。
ここに属性が表示されます。
ここにファイル内容が表示されます。
結果の非表示
ファイルの読込
行Mで入力したファイル群のオブジェクトを引数 files として関数 fileReader が呼び出されます(行A)。
行Bでの files.length は選択ファイルの個数で、行C以降で個々のファイル名やタイプが得られます。ここまでは、fileList と同じです。
var reader = new FileReader(); により、ファイルの内容を読み込む FileReaderオブジェクト を生成し、ファイルの内容を非同期で取得することができます(reader の名称は任意ですが、一般に「reader」が使われています)。
行Eの「タイプ.match('text.*')」の 'text.*' は正規表現 で、
text:文字列「タイプ」の先頭部分が「text」で、
.* :次に改行コード以外の任意文字が続く
ならば真、そうでなければ偽になります。
ここでは、「タイプが text/plain や text/html などのとき」という意味になります。
同様に、行Iは「タイプが image/jpeg や image/gif など画像ファイルのとき」となります。
行Fと行Hの関係は、行Hのreader.readAsText でファイルを読み、読み終わったら(行Fのreader.onload )の function を実行する」という関係です。すなわち、onload は readAsText の実行以前にイベントが発生したときの処理を記述しておくことになります。
行Jと行Lも行Fと行Hの関係と同じです。
(このような処理にするのは、file API が非同期アクセスを標準にしているからです。)
テキストファイルの取扱
reader.readAsText(ファイル, "utf-8"); とは、「「ファイル」を文字コード(utf-8)のテキストデータ(AsText)として読込み、その内容をオブジェクト(reader)に入れる」という意味です。
ここで指定した文字コードとファイルの文字コードが異なると文字化けします。事前に文字コードを知っておく必要があります。
行Fでは function により、ファイルのテキストが入っているevent.target.result をそのまま表示させています(ここでのevent は任意の名称でよいのですが、「読込イベント」なので、event を変数名にするのが通常です)。
「テキスト内容 = event.target.result;」とすると、「テキスト内容」にはプレーンテキストの改行もそのままの状態で入っています。しかし、
document.getElementById("表示場所").innerHTML = テキスト内容;
としたとき、自動的に改行が無視されてしまいます。
画像ファイルの取扱
行LのreadAsDataURL は、DataURL形式 で読み込みます。
DataURL形式とは画像や音声データのURLなど(画像そのものではない)の情報です。
そのため、行Jで(テキストデータでの行Fのように)単純に event.target.result としたのでは、画像は得られません。行K1~K5の処理が必要です。
K1では<div>-</div>の要素を、K2では<img>要素を生成します。K3で、event.target.result (ファイルのurl)を<img>要素に組み込み、K4で<div>の内部(child)に<img>要素を組み込みます。
その結果、K5でのtagDiv.innerHTML には、
<div><img src="画像ファイルのURL"></div>
となり(これは正確な記述ではありません)、すなわち画像が取り出されます。
表示される画像は、ペイントで開いたような画像です。縮小表示させるには、width や height をK1~K5内に組み込むか、style で定義しておく必要があります。
HTMLファイルでの留意事項
行Fの document.getElementById("内容表示場所").innerHTML のように、このページ内に表示した場合、「内容表示場所」にHTMLを記述したのと同じ状況になります。
リンク先や画像など他のファイルのURLが記述されている場合、それが相対指定だと、このページ(プログラムのあるページ)からの相対指定だとされるので、正しく動作しません。
styleやscriptがあり、このページと同名の指定があると、ファイルでの指定が優先されるので、このページ画面の他の部分にまで影響してしまいます。
ローカル画像ファイルの表示(簡素化)
一つのローカル画像ファイルだけを対象にするときは、かなり簡素なスクリプトになります。
function fileReaderImage(files, 表示場所) { // ア
var reader = new FileReader(); // イ
reader.onload = function(event) { // ウ
var tagDiv = document.createElement('div'); // エ <div> pでもspanでもよい
var tagImg = document.createElement('img'); // オ <img
tagImg.src = event.target.result; // カ <img src=~>
// tagImg.width = 200; // キ width, height
tagDiv.appendChild(tagImg); // ケ <div><img src=~>
document.getElementById(表示場所).innerHTML = tagDiv.innerHTML; // コ
} // サ
reader.readAsDataURL(files[0]); // シ 画像ファイルを読み込む
} // ス
<input type="file" onChange="fileReaderImage(this.files)"></input></p> // セ
<div id="画像表示場所"></div> // ソ <div>は何でもよい