IT系おじさんのチラシの裏
2018年10月~
当サイトの記事にはアフィリエイト広告のリンクが含まれる場合があります

JavaScriptでファイル名順に複数ファイルを読み込む方法

INPUTタグで複数ファイルを読み込む際、ブラウザ内で処理するときはFileReaderオブジェクトを使うことが多いと思います。

しかしこれは非同期処理なので、はてファイル名順に処理する場合はどうしたものか、とちょっと悩んだので備忘録としてメモしておきます。

具体的には連番の画像ファイルを順番に並べたい、とかですね。

バラバラに処理しても良い場合

サンプルコード

<input type="file" id="input_file" multiple>
<script>
let imgArray = [];
document.getElementById('input_file').onchange = function () {
	for (let i = 0; i < this.files.length; i++) {
		let reader = new FileReader();
		reader.onload = function() {
			let img = new Image();
			img.src = this.result;
			img.onload = function () {
				imgArray.push(img); //←ここで画像データをメモリ内に保存
			}
		};
		reader.readAsDataURL(this.files[i]);
	}
};
</script>

解説

選択された複数の画像ファイルをメモリ中にロードする例ですが、このコードではどの順番に画像が読み込まれるか不確定です。実際試してみると01.png,02.png,03.png...という連番ファイルであっても、02.png,01.png,03.pngというような順番に読み込まれることがあります。

ファイル名をキーにして連想配列をソートする

サンプルコード

<input type="file" id="input_file" multiple>
<script>
let imgArray = [];
document.getElementById('input_file').onchange = function () {
	let imgTemp= []; //←一時保存用
	let files_length = this.files.length;
	for (let i = 0; i < this.files.length; i++) {
		let reader = new FileReader();
		let filename = this.files[i].name;
		reader.onload = function() {
			let img = new Image();
			img.src = this.result;
			img.onload = function () {
				imgTemp[filename] = this;
				if (Object.keys(imgTemp).length >= files_length) {
					imgArray = [];
					let keys = Object.keys(imgTemp);
					keys.sort();
					for (key of keys) {
						imgArray.push(imgTemp[key]);
					}
				}
			}
		};
		reader.readAsDataURL(this.files[i]);
	}
};
</script>

解説

…若干、メモリの無駄遣いというか、強引な気がしなくもないですが、一時的にファイル名をキーとした連想配列(imgTemp)を作り、選択されたファイル数まで揃ったら、キーをソートして、保存用の配列(imgArray)にキー順にほおりこむ、という処理をしています。

まとめ

もっとスマートなやり方がありそうなのでググってみたのですが、むしろFileReaderのonload中にファイル名を取得するにはどうすれば良いんだ?という掲示板の書き込みとか、それをなんかやたら小難しい方法で解決している書き込みしか見当たりませんでした。

FileReaderオブジェクトにファイル名を保存しておければわかりやすいんですけどね。

見た目的にreader.onloadの中からfilenameを参照したら、後で書き換わるように感じるのかも知れません。昔のJavaScriptのvar変数はグローバルスコープだったから、というのも理由のひとつかも。

いずれにせよ、ループ内でlet宣言で作成された変数filenameは、onloadでセットしている無名関数に値渡しされるので、どんな順番で呼ばれようとfilenameが書き換わることはありません。

…などと言いつつ、自分自身が3歩歩いたら忘れそうなのでここにメモしておきました。

関連記事

JavaScriptのcanvasで縦書きを行う際の備忘録

canvas上に縦書きの文章を出力して画像化しようと考えてちょっとハマったので忘れないうちにメモしておきます。 結論から先に書くと、基本的にcanvasにはwriting-modeの設定が効くの

JavaScriptのWebAudioAPIで楽曲の口パクをしてみる

以前、ソフトウェアの解説動画を作った際、おっさんの声だけ流れてるのもアレだし、最近流行りのアバターにしゃべらせるやつやってみよう、と思ったことがあります。 vtuberとかおじさんよくわからない

コメント

新しいコメントを投稿する

[新規投稿]
 
TOP