我正在编程允许用户在网络服务器上存储文档和图片,以便以后存储和检索。当用户将文件上传到我的服务器时,PHP 会根据扩展名告诉我它是什么文件类型。但是,我担心用户可以将 zip 文件重命名为 somezipfile.png 并存储它,从而在我的服务器上保留一个 zip 文件。有什么合理的方法可以打开上传的文件并“检查”它是否真的属于上述文件类型?
9 回答
幻数。如果您可以读取二进制文件的前几个字节,您就可以知道它是什么类型的文件。
查看 PHP 的FileInfo PECL 扩展,它可以为您执行 MIME 魔术查找。
有点。大多数文件类型都保留了一些字节来标记它们,这样您就不必依赖扩展名。网站http://wotsit.org是一个很好的资源,可用于查找特定类型的信息。
如果您使用的是 unix 系统,我相信 file 命令不依赖于扩展名,因此如果您不想编写字节检查代码,则可以使用它。
对于 PNG ( http://www.w3.org/TR/PNG-Rationale.html )
PNG 文件的前 8 个字节始终包含以下值:
(十进制) 137 80 78 71 13 10 26 10
(十六进制) 89 50 4e 47 0d 0a 1a 0a
(ASCII C 表示法)\211 PNG \r \n \032 \n
许多文件类型在文件开头都有“幻数”来识别它们,您可以从文件前面读取一些字节并将它们与已知幻数列表进行比较。
如果您只处理图像,那么 getimagesize() 应该区分有效图像和假图像。
$ php -r 'var_dump(getimagesize("b&n.jpg"));'
array(7) {
[0]=>
int(200)
[1]=>
int(200)
[2]=>
int(2)
[3]=>
string(24) "width="200" height="200""
["bits"]=>
int(8)
["channels"]=>
int(3)
["mime"]=>
string(10) "image/jpeg"
}
$ php -r 'var_dump(getimagesize("/etc/passwd"));'
bool(false)
getimagesize 的错误值不是图像。
在 unix 系统上,捕获“文件”命令的输出应该提供足够的信息。
有关如何在 PHP 中快速执行此操作的确切答案,请查看以下问题:How do I find the mime-type of a file with php?
作为旁注,我遇到了一个类似的问题,我必须自己进行类型检查。我的应用程序的前端接口是在 Flash 中完成的。这些文件正在通过 flash 传递给 php 脚本。当我尝试使用 php 进行 MIME 类型检查时,返回的类型总是 application/octetstream,因为它来自 flash。
我必须实现一个幻数类型范例。我只是创建了一个 xml 文件,其中包含文件类型以及在文件开头找到的一些定义模式。文件到达服务器后,我对 xml 文件进行了一些模式匹配,然后接受或拒绝了该文件。我也没有注意到任何预期的实际性能下降。
对于可能在前端使用 Flash 并在上传文件后尝试键入检查文件的任何人,这只是一个旁注。
除了识别文件类型外,您可能还需要注意嵌入或附加了其他文件的文件。不幸的是,这需要对文件内容进行更深入的分析,而不仅仅是使用“幻数”。
例如, http: //quantumrook.wordpress.com/2007/06/06/hide-a-rar-file-in-a-jpg-file/(这种特殊类型的数据隐藏可以通过加载和将实际图像数据重新保存到新文件中..其他会更困难。)