如何根据扩展名验证文件类型?
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
}
我想创建一个上传脚本,我想定义一些允许上传的文件类型,以防止通过重命名文件扩展名来欺骗我使用这个数组: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
}