よく使うのに毎回ググっていたりするので、残しておきます。
単純に選択した画像を表示するだけのコード
"load"イベントの処理を変更すれば画像以外のものにも使えます。
テキストファイルの場合は、readAsDataURLの代わりに
reader.readAsText(file);
を使います。
// <input type="file" id="input_file">、<img id="image">の場合
//通常版
const input_file = document.getElementById("input_file");
input_file.addEventListener("change", function (e) {
const file = e.target.files[0];//複数ファイルはfiles配列をループで回す
const reader = new FileReader();
const image = document.getElementById("image");
reader.addEventListener("load", function () {
image.src = reader.result;
}, false);
if (file) {
reader.readAsDataURL(file);
}
})
//jQuery版
$("#input_file").change(function (e) {
const file = e.target.files[0];
const reader = new FileReader();
reader.addEventListener("load", function () {
$("#image").attr("src", reader.result);
}, false);
if (file) {
reader.readAsDataURL(file);
}
});
readAsDataURLの代わりにcreateObjectURLを使う
上の例ではFileReader()のreadAsDataURLを使って読み込みました。
画像のようにバイナリデータの場合はcreateObjectURLを使うこともできます。この方が記述はシンプルですね。
用が済んだらURL.revokeObjectURL();でメモリを解放したほうがいいみたいです。
const file = e.target.files[0];
const blobURL = URL.createObjectURL(file);
image.src = blobURL;
image.addEventListener('load', function () {
URL.revokeObjectURL(blobURL);
});
inputタグのaccept属性でファイルの種類を制限する
inputタグでは、accept属性で受け付けるファイルの拡張子やMIMEを制限できます。
拡張子で指定。複数指定はカンマ区切り。拡張子とMIMEの併用も可能。
拡張子の場合は大文字、小文字両方書いておいた方が良い
<input type="file" accept=".jpg,.png,.JPEG,.PNG">
MIMEで画像ファイルならなんでも
<input type="file" accept="image/*">
MIMEでテキストファイルを指定
<input type="file" accept="text/plain">
Fileオブジェクトのプロパティ
ファイルオブジェクトから最後の変更日時、ファイル名、ファイルタイプ、ファイルサイズが取得できます。
パスは取れません。
//--- 最終変更日時
file.lastModified;
// 1641865381042 UNIX時間
new Date(file.lastModified);
// Tue Jan 11 2022 10:43:01 GMT+0900 (日本標準時)
//-- ファイル名
file.name;
// 'hoge.jpg'
//-- ファイルタイプ
file.type;
//'image/jpeg'
//-- ファイルサイズ
file.size;
//48867 ※byteで返る
ファイルパスは取れないっぽい
普通に考えると、いちいちfile readerで読み込まずにファイルパスだけ取得してimgタグのsrcに設定したくなります。
しかし、昔はともかく今のブラウザではセキュリティ上ファイルパスの取得はできないみたいです。
${input要素}.value
でファイルパスが取得できるという情報もありますが、実際にやると
C:\fakepath\hoge.png
といった形で、ファイル名以外はfakepath
という文字列に置き換えられています。
file.webkitRelativePathという属性もありますが非標準で推奨されてない感じです。
複数ファイルを同時選択する場合の処理
ファイル選択ダイアログで複数ファイルを選択したい時は、
<input type="file" multiple>
のようにmultipleオプションを付けます。
複数ファイルの処理はfor (file of e.target.files)
で回すと良い感じです。
この例では指定した画像をimgタグでBodyに追記していきます。
//<input type="file" id="input_file" multiple> の場合
input_file.addEventListener("change", function (e) {
for (const file of e.target.files) {
const image = new Image();
const blobURL = URL.createObjectURL(file);
image.src = blobURL;
image.addEventListener('load', function () {
URL.revokeObjectURL(blobURL);
document.body.appendChild(image);
});
}
}, false);