如何根据扩展名验证文件类型?

How to validate a file type against its extension?

我想创建一个上传脚本,我想定义一些允许上传的文件类型,以防止通过重命名文件扩展名来欺骗我使用这个数组:PHP / Mime Types - List of mime types publically available? 首先它检查是否允许文件扩展名(例如 .xsl),然后它使用 finfo 获取 mimtype 以检查该数组以查看 mimetype 是否与扩展名匹配。

我上传了一个 .xsl 文件,finfo 将文件类型重新运行为 application/octet-stream 但 xsl 扩展数组 returns application/x-msexcel 因此它不相等且未被验证。

我真的应该忘记 mimetype 与脚本的文件扩展名验证器匹配,我应该只检查文件扩展名吗?或者我应该怎么做?

基本上你做对了。你永远不应该依赖从上传表单发送的 mime 类型 headers,因为你可以很容易地伪造它或者它不存在,那么你通常会得到 application/octet-stream header.

因此,这是检查文件扩展名是否与该文件扩展名允许的 MIME 类型相匹配的好方法。

我看到你链接了这个列表 here。这当然是一个很好的列表,但对于 php 来说并不是真正有用的,因为数组中的覆盖太多,例如:

$mimeTypes = array(
    'xlm' => 'application/vnd.ms-excel',//overridden
    'xlm' => 'application/x-excel',
    'xls' => 'application/excel',//overridden
    'xls' => 'application/vnd.ms-excel'
);

var_dump( $mimeTypes );

这只会输出两个值而不是四个,你应该使用这样的数组:

$mimeTypes = array(
    'xlm' => array( 'application/vnd.ms-excel', 'application/x-excel' ),
    'xls' => array( 'application/excel', 'application/vnd.ms-excel' ),
    'txt' => array( 'text/plain' )
);

var_dump( $mimeTypes );

因此,如果您已经有了文件扩展名,您只需使用 in_array() 检查 mimetype。

这是您可以解决的基本示例。 注意:这不是一个有效的例子,但我想你知道我想指出的地方:

// you have your file, you said it´s excel but you uploaded it with extension txt
$filepath = "excel.txt";

if( strpos( $filepath, '.' ) === false ) {
    // no file extension
    // return ?
}
// get the file extension
// well there is surely a better way
$filenameParts = explode( ".", $filepath );
$fileExt = array_pop( $filenameParts );// return the las element of the array and REMOVES it from the array

// your fopen stuff to get the mime type
// ok let´s say we are getting back the follwing mime type
$fileMimeType = 'application/vnd.ms-excel';

// now check if filextension is in array and if mimetype for this extension is correct
if( isset( $mimeTypes[$fileExt] ) && in_array( $fileMimeType, $mimeTypes[$fileExt] ) ) {
    // file extension is OK AND mime type matches the file extension
} else {
    // not passed unknown file type, unknown mime type, or someone tricked you
    // your excel.txt should end up here
}