PHPでアップロードしたファイルタイプ取得

PHP

ユーザがブラウザからファイルをアップロードした際に、サーバでファイルタイプをチェックする方法。

おおまかに、ブラウザの環境変数から検証する方法と、サーバ側でチェックする方法がある。

簡単にチェック

まず、$_FILES変数にファイルタイプが設定されているのでこれを使う例。
typeというキーに入っています。

print_r($_FILES);
Array
(
    [file] => Array
        (
            [name] => site-csv-200902261653.csv
            [type] => text/comma-separated-values
            [tmp_name] => /tmp/phpMaX6wO
            [error] => 0
            [size] => 3604
        )

)

しかしながら、ブラウザによってこの値は異なります。(Windows VistaでCSVファイルをアップロードして検証)
Chromeに至っては、null。。。。

  • FF3:text/comma-separated-values
  • IE7:application/octet-stream
  • Opera: text/comma-separated-values
  • safari: application/octet-stream
  • chrome: null

type変数を信じる場合は、メジャーなブラウザの場合は以下のコードで検証できます。これは、ブラウザ出力を信頼する場合。

$valid_type = array('text/comma-separated-values','application/octet-stream',null);

if(in_array($_FILES['file']['type'], $valid_type){
  print 'valid';
}else{
  print 'invalid';
}

しっかりチェック

サーバ側でちゃんとやるためには、Fileinfoライブラリを使う。
FileinfoはPECLで提供されている。libmagicライブラリに依存している。

# aptitude install libmagic-dev
# pecl install fileinfo

php.iniに以下を追加して、サーバ再起動。

extension='fileinfo.so'

以下のように書けば、ファイルタイプを返してくれる。

$finfo = finfo_open(FILEINFO_MIME);
echo finfo_file($finfo, $csv_file) . "\n";
finfo_close($finfo);
text/plain charset=unknown 

判定は以下のように。

$finfo = finfo_open(FILEINFO_MIME);
$type = finfo_file($finfo, $csv_file) ;
finfo_close($finfo);

if(strpos($type, 'text/plain') !== false){
  print 'valid';
}

コメント