【PHP】PHPがファイルのMIMEタイプを検出する方法

  • 2022年8月10日
  • PHP

 PHPにはmime_content_typefinfo_bufferといったファイルの種類を検出する関数があります。これらの関数にファイルを渡すとimage/gif、text/plainといった様にファイル形式を文字列で返してくれます。このファイル形式を表す文字列をMIMEタイプと言います。

PHP: mime_content_type – Manual
PHP: finfo_buffer – Manual

 PHPがこのMIMEタイプを返す仕組みについて紹介します。

 ざっくばらんに言えば以前記事にした際に用いた File Signatures で定義されているファイルの形式のチェックをしています。

File Signatures
【PHP】ファイルの中身からファイル形式を識別する – 株式会社シーポイントラボ | 浜松のシステム・RTK-GNSS開発

 File Signatures はファイルの先頭にあるファイル形式ごとに定まったバイト列です。例えば、PNG画像ファイルならば\x89\x50\x4e\x47\x0d\x0a\x1a\x0aとなり、次の画像の様にテキストエディタから見えます。

 PHPはこれを元に、ファイルの中身に対応する MIME Content-type を出力します。

 PHPの MIME Content-type 関連の処理は次のディレクトリ内に含まれます。

php-src/ext/fileinfo at PHP-8.1 · php/php-src
php-src/ext/fileinfo/libmagic at PHP-8.1 · php/php-src

 MIME Content-type 関連の処理は特に libmagic 以下に集中しています。libmagic という名前のディレクトリの中身はライブラリの libmagic の PHP 版です。元々は単純なクローンだった様ですが PHP 内部に組み込まれて年月が経つうちに徐々に変わりました。とはいえ基本はライブラリとしての libmagic なので次の本家と同じ部分も多いです。

file/file: Read-only mirror of file CVS repository, updated every half hour. NOTE: do not make pull requests here, nor comment any commits, submit them usual way to bug tracker or to the mailing list. Maintainer(s) are not tracking this git mirror.

 ファイルに含まれるバイト列とファイル形式の対応を行ってMIMEタイプを出力するには辞書的なデータベースが必要です。PHP組み込みのデータベースは次に入っています。

php-src/create_data_file.php at PHP-8.1 · php/php-src
php-src/data_file.c at PHP-8.1 · php/php-src

 create_data_file.php というスクリプトで PHP に組み込むためのデータベースを作っています。data_file.c の配列を検索すると含まれているバイト列が File Signatures のそれだとわかります(0x89, 0x50, 0x4E, 0x47,などがヒットします)。

 このデータベースは実は外部から与えることができます。これは MIME Content-type を得られる関数であるfinfo_bufferを使うための関数であるfinfo_open内で設定できます。

PHP: finfo_open – Manual

 これを用いることで次の様にオリジナルのファイル形式をオリジナルのMIMEタイプとして返すこともできます。

<?php

// データベースにオリジナルの File Signatures とMIMEタイプの対応表ファイルを渡す 
$finfo    = finfo_open(magic_database: __DIR__.DIRECTORY_SEPARATOR.'tmp.magic');
// 定義したバイト列に沿うバイト列を渡し、MIMEタイプを返させる
$mimeType = finfo_buffer($finfo, "\x11Cplab適当な中身", FILEINFO_MIME_TYPE);
// 独自定義のMIMEタイプが返ってくる
echo $mimeType."\n"; // app/cplab
# tmp.magic
# original file.
0	string		\x11Cplab     Original File Format
!:mime	app/cplab
>株式会社シーポイントラボ

株式会社シーポイントラボ

TEL:053-543-9889
営業時間:9:00~18:00(月〜金)
住所:〒432-8003
   静岡県浜松市中央区和地山3-1-7
   浜松イノベーションキューブ 315
※ご来社の際はインターホンで「316」をお呼びください

CTR IMG