验证-如何检查PHP中已上传文件的文件类型?
在PHP网站上,他们建议的唯一实际检查是在此处使用getimagesize()或move_uploaded_file()。 当然,出于多种原因,您通常不希望用户上传任何类型的文件。
因此,我经常使用一些“严格”的MIME类型检查。 当然,这是非常有缺陷的,因为通常哑剧类型是错误的,并且用户无法上传其文件。 伪造和/或更改也非常容易。 除此之外,每种浏览器和操作系统对它们的处理方式也不同。
另一种方法是检查扩展名,这当然比mime类型更容易更改。
如果只需要图像,则可以使用像getimagesize()这样的图像。
那其他类型的文件呢? PDF,Word文档还是Excel文件? 甚至是纯文本文件?
编辑:如果您没有mime_content_type或Fileinfo,并且system(“ file -bi $ uploadedfile”)给您错误的文件类型,还有哪些其他选择?
7个解决方案
33 votes
看一下mime_content_type或Fileinfo。 这些是内置的PHP命令,用于通过查看文件内容来确定文件的类型。 还要检查以上两页上的评论,还有其他一些好的建议。
就我个人而言,我运气很好,基本上使用了system("file -bi $uploadedfile"),但我不确定这是否是最好的方法。
davr answered 2020-06-20T03:00:00Z
14 votes
恕我直言,所有MIME类型检查方法都没有用。
假设您的文件应具有MIME类型application/pdf。标准方法试图查找看起来像PDF标头的文件(%PDF-或smth。类似这样),它们将在上面返回“好吧,好像这是PDF文件” 成功。 但这实际上并不代表任何意义。 您可以上传仅包含%PDF-1.4的文件,该文件将通过MIME检查。
我的意思是,如果文件具有预期的MIME类型-它将始终通过MIME类型检查,否则结果不确定。
Sudden Def answered 2020-06-20T03:00:29Z
2 votes
我假设您将要接受一个固定的文件类型白名单。
对于每种类型,您将不得不使用不同的技术来验证它们是否是该格式的有效示例。
有两个相关的问题:
它看起来大概像是正确的类型吗? (如前所述,对于JPEG,您可以检查标题。对于许多基于Unix的格式,您可以检查“魔术cookie”。)
它实际上是该类型的有效示例吗(例如,对于任何类似XML的格式,您可以针对DTD进行验证。)
我认为,对于每种格式,您应该针对每种格式分别提出问题,因为与ZIP文件相比,PDF的答案将大不相同。
Oddthinking answered 2020-06-20T03:01:12Z
2 votes
我使用了与PHP 5.2兼容的mime_content_type,因为我不能使用被提供商禁用的Fileinfo(需要PHP 5.3)和system()。例如,我检查文件是否为文本文件,因此:
if (strcmp(substr(mime_content_type($f),0,4),"text")==0) { ... }
您可以在以下位置的“ PHP目录和子目录侦听器以及文件查看器和下载器”中查看完整的示例:[http://www.galgani.it/software_repository/index.php]
Francesco Galgani answered 2020-06-20T03:01:36Z
2 votes
if(isset($_FILES['uploaded'])) {
$temp = explode(".", $_FILES["uploaded"]["name"]);
$allowedExts = array("txt","htm","html","php","css","js","json","xml","swf","flv","pdf","psd","ai","eps","eps","ps","doc","rtf","ppt","odt","ods");
$extension = end($temp);
if( in_array($extension, $allowedExts)) {
//code....
} else {
echo "Error,not Documentum type...";
}
}
Krausz Lóránt Szilveszter answered 2020-06-20T03:01:52Z
1 votes
这是iZend的功能file_mime_type:
function file_mime_type($file, $encoding=true) {
$mime=false;
if (function_exists('finfo_file')) {
$finfo = finfo_open(FILEINFO_MIME);
$mime = finfo_file($finfo, $file);
finfo_close($finfo);
}
else if (substr(PHP_OS, 0, 3) == 'WIN') {
$mime = mime_content_type($file);
}
else {
$file = escapeshellarg($file);
$cmd = "file -iL $file";
exec($cmd, $output, $r);
if ($r == 0) {
$mime = substr($output[0], strpos($output[0], ': ')+2);
}
}
if (!$mime) {
return false;
}
if ($encoding) {
return $mime;
}
return substr($mime, 0, strpos($mime, '; '));
}
iZend answered 2020-06-20T03:02:12Z
0 votes
对于PHP> = 5.3.0,可以使用php的file(finfo_file)函数获取有关文件的文件信息。
对于PHP <5.3.0,可以使用系统的file命令来获取文件信息。
因此,只需使其成为一个函数,
var_dump(mime_type("wiki templete.txt")); // print string(10) "text/plain"
function mime_type($file_path)
{
if (function_exists('finfo_open')) {
$finfo = new finfo(FILEINFO_MIME_TYPE, null);
$mime_type = $finfo->file($file_path);
}
if (!$mime_type && function_exists('passthru') && function_exists('escapeshellarg')) {
ob_start();
passthru(sprintf('file -b --mime %s 2>/dev/null', escapeshellarg($file_path)), $return);
if ($return > 0) {
ob_end_clean();
$mime_type = null;
}
$type = trim(ob_get_clean());
if (!preg_match('#^([a-z0-9\-]+/[a-z0-9\-\.]+)#i', $type, $match)) {
$mime_type = null;
}
$mime_type = $match[1];
}
return $mime_type;
}
MimeTypes
Kris Roofe answered 2020-06-20T03:02:45Z