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