ファイルアップロード機能を実装するためのソースコードはネット上に多く出回っているので、実装するのはそれほど難しいことではありません。

機能を作る時に重要になるのが、不適切な形式のファイルはアップロードできないことです。拡張子チェックなどの処理が実装されていない状態で、悪意のあるユーザーが不適切なファイルをアップロードしてくる可能は大いに考えられます。

本記事では、Files APIを使用してJavaScriptで拡張子のチェックを行う方法を紹介します。Files APIについて概要が知りたい方は、前回解説した記事でイメージを掴むことができるので、読んでみてください。

Files APIに関する解説記事 : /different-blob-arraybuffer

拡張子チェックを実装する

WEB開発ではフロントエンドでの拡張子チェックは行わず、サーバーサイドで厳密にチェックするケースと、フロントエンドとバックエンドの両方でチェックを行うケースがあります。

二重でチェックを行えばセキュリティレベルは上がりますが、改修コストは2倍になるので無駄な工数をかけずに開発を進める場合には、サーバーサイドでの拡張子チェックのみでも問題はないと思われます。

PHPでの拡張子チェック解説記事はこちら : /php-extension-check

では簡単にJavaScriptでの拡張子チェックの流れを解説します。

処理の流れ

・許可する拡張子を指定する

・ファイル名の拡張子を取得する

・許可された拡張子かどうかを判断する

・判定を通過した場合のみアップロード

サンプルコード

コピペで動作するので、いろいろな拡張子を指定して確認してみてください。保守性を意識して無名関数ではなく、オブジェクト指向で記述しています。

処理の解説はコメントに記述しているので、順に処理を追ってみてください。

■ HTML

 <input type="file" id="localFileInput">

JavaScript ファイルの選択を検知する

const fileInput = document.getElementById('localFileInput');
// ファイル選択
fileInput.addEventListener('change', function(e) {
  const target = e.target;
  get_extension(target);
});

■ JavaScript 拡張子を取得

function get_extension()
{
  let fileName = target.files[0].name;
  // ファイル名の末尾のカンマの位置を取得
  const position = fileName.lastIndexOf('.');
  // indexから一つ目の配列要素を切り取り拡張子を取得
  const extension = fileName.slice(position + 1);

  // チェックの処理に拡張子を渡す
  check_extension(extension);
}

■ JavaScript 拡張子チェック

function check_extension(extensionName) {
  // 許可する拡張子を指定
  const extensionArray = ['jpg', 'png', 'jpeg'];
  // 拡張子文字列を小文字に変換
  const extension = extensionName.toLowerCase();
  // 許可配列から一致する値を検索
  if(extensionArray.indexOf(extension) !== -1) {
    // アップロード
    file_upload();
  } else {
    console.log('ファイル形式が不適切です。');
  }
}

■ JavaScript ファイルアップロード(仮)

function file_upload() {
  console.log('ファイル形式が適切でした。アップロードを開始します');
}

複数ファイルアップロードに対応する

上記のサンプルコードでは単一ファイルの拡張子チェックなので、複数ファイルに対応した処理も記述します。こちらもコピペで動きますので動作を確認してみてください。

■ HTML

単一チェックとの変更点

・複数ファイルのアップロードに対応するために、name属性の末尾に[]を記述

・input[type=”file”]にmultiple属性を追加

・onclick属性に拡張子チェックを行う関数を指定し、引数にイベントを渡す(submitのイベントを無効化するため)

<form action="">
  <input type="file" id="localFileInput" name="upload[]" multiple="multiple">
  <input type="button" onclick="check_form(event)" value="送信">
</form>

■ JS 拡張子チェック

変更点

・複数ファイルを取得して、ループ処理でファイル数分のチェックを行う

function check_multiple_file(event) {
   // イベント処理の無効化
  event.preventDefault();
   // 選択された複数のFileListを取得
  const fileInputs = document.getElementsByName('upload[]')[0].files;
   // ファイル数分のチェック
  for (let i = 0; i < fileInputs.length; i++) {
    get_extension(fileInputs[i]);
  }
}

その他の拡張子の処理は同じです。

番外編 : 怪しいファイルの見分け方

ファイルの名前には、.jpg, .txt, .htmlのように、.(ドット)+3~4文字からなる「拡張子」が付与されています。MacやWindowsなどにはシステムの動作ファイルというものがあり、それらをむやみに削除されないように「隠しファイル」として表示していないものが存在します。

悪意のあるユーザーはこれらの実行可能な動作ファイルを、その他のwordやexcelに成り済ましてアップロードを試みてくるケースもあります。

注意すべきファイルの拡張子

・exe
・com
・bat
・cmd
・pif
・scr

・VBS
・VBE
・JS
・JSE
・WSF
などのスクリプトファイルには注意が必要です。

WEB開発では、このようなセキュリディを考慮してプログラミングをすることも求められます。

参考 : https://developer.mozilla.org/ja/docs/Web/API/File

カテゴリー: JavaScript