PHPのFileinfo(finfo)で、ファイルの種類を表示しよう

例えば、ユーザーが画像をアップロードできるサービスを作成する場合、本当にユーザーがアップロードしたファイルが画像であることを確認してからなければ、画面に表示できないばかりか、コンピューターウィルスを仕込まれたりなどの危険性があります。

PHPでは、ファイルのアップロード自体は次の方法でできます。まずは、フォームを準備してtype属性がfileになっているエリアを準備します。

<form action="" method="post" enctype="multipart/form-data">
    <input type="file" name="myまたはfile">
    <button type="submit">送信する</button>
</form>

またこの時、formタグにenctype="multipart/form-data"属性を追加する必要があります。これで、ファイルを送信できます。

$_FILESのtypeは信用しない

この時、PHPは$_FILESというグローバル変数にアップロードされたファイルが格納され、次のような要素の配列で各要素を取得できます。

  • name: ファイル名
  • type: ファイルの種類(MIMEタイプ)
  • size: ファイルのサイズ
  • tmp_name: 一時的に保存されている場所のパス
  • full_path: ファイルパス

となり、この中にtypeという値があるため、これでファイルの種類を知ることができます。しかし、この値は信用することができません。Webブラウザーから渡された値であるため、偽装されている可能性がゼロとはいえないのです。

そこで、実際にアップロードされたファイルを使って、改めてファイルタイプやファイルサイズを取得するとよいでしょう。

mime_content_typeファンクションは非推奨?

ファイルの種類のことを「MIMEタイプ(マイムタイプ)」といい、PHPでこのMIMEタイプを取得する場合、mime_content_typeというファンクションがあります。

しかし、2022年現在ではこのファンクションは使いにくいファンクションです。一時期は「非推奨」という扱いになり、廃止が検討されていたり、また現在でも標準では利用できずに「php.ini」という設定ファイルを編集しなければ使えない環境などもあります。

そこで、代わりに使いたいのはFileinfoファンクション、またそれをクラス化しかfinfoというクラスです。ここでは、finfoを利用しましょう。

finfoクラスが利用できるか確認しよう

PHPの設定によっては、finfoクラスが使えずに次のようなエラーメッセージが表示されることがあります。

Uncaught Error: Class “finfo” not found in

この場合は、php.iniに次のように書き加えましょう。

extension=php_fileinfo.dll

こうしてサーバーを再起動すれば利用できるようになります。

finfoクラスとは

finfoクラスは、PHP5.3から利用できるようになったクラスで、fileinfoファンクションのインタフェースというものです。これは、PHPでオブジェクト指向のプログラミングができるように、旧来のファンクションをクラスにしたもので、PHPにはこのようなクラスがいくつかあります。

これを使うには、まずは次のように宣言します。

$finfo    = new finfo();

そしたら、fileメソッドで各情報を取得できます。

$finfo = new finfo();
$mimetype = $finfo->file( $path, FILEINFO_MIME_TYPE );
echo $mimetype; // image/jpeg など

これで、ファイルのMIMEタイプを取得できます。例えば、JPEG画像の場合は「image/jpeg」などと表示されます。これを利用しましょう。

ちなみに、ファイルサイズも$_FILESの値を利用せずに、filesizeファンクションを利用して、実際にサイズを取得するとよいでしょう。

$filesize = filesize( $path );
echo $filesize;

この記事を書いた人

たにぐち まこと

『よくわかるPHPの教科書』や『マンガでマスター プログラミング教室』の著者。 ともすた合同会社で、プログラミング教育やこども向けの講座などを Udemyや YouTubeで展開しています。