我正在开发一个简单的php上传脚本,用户只能上传ZIP和RAR文件。
我应该使用哪些MIME类型检查$_FILES[x][type]
?(请提供完整清单)
谢谢..
我正在开发一个简单的php上传脚本,用户只能上传ZIP和RAR文件。
我应该使用哪些MIME类型检查$_FILES[x][type]
?(请提供完整清单)
谢谢..
Answers:
来自freedompeace,Kiyarash和Sam Vloeberghs的答案:
.rar application/x-rar-compressed, application/octet-stream
.zip application/zip, application/octet-stream, application/x-zip-compressed, multipart/x-zip
我也要检查文件名。这是检查文件是RAR还是ZIP文件的方法。我通过创建一个快速的命令行应用程序对其进行了测试。
<?php
if (isRarOrZip($argv[1])) {
echo 'It is probably a RAR or ZIP file.';
} else {
echo 'It is probably not a RAR or ZIP file.';
}
function isRarOrZip($file) {
// get the first 7 bytes
$bytes = file_get_contents($file, FALSE, NULL, 0, 7);
$ext = strtolower(substr($file, - 4));
// RAR magic number: Rar!\x1A\x07\x00
// http://en.wikipedia.org/wiki/RAR
if ($ext == '.rar' and bin2hex($bytes) == '526172211a0700') {
return TRUE;
}
// ZIP magic number: none, though PK\003\004, PK\005\006 (empty archive),
// or PK\007\008 (spanned archive) are common.
// http://en.wikipedia.org/wiki/ZIP_(file_format)
if ($ext == '.zip' and substr($bytes, 0, 2) == 'PK') {
return TRUE;
}
return FALSE;
}
请注意,它仍然不能100%确定,但是可能已经足够好了。
$ rar.exe l somefile.zip
somefile.zip is not RAR archive
但是,即使WinRAR也将非RAR文件检测为SFX存档:
$ rar.exe l somefile.srr
SFX Volume somefile.srr
application/x-zip-compressed
multipart/x-zip
可能如何有效?它不是多部分的。SitePoint列表包含许多不正确的MIME类型,而且还远远不够完整。正式的IANA媒体类型注册机构尚未(也可能不会)100%完成。
可以在Internet编号分配机构(IANA)上找到哑剧类型的正式列表。根据他们的名单Content-Type
报头zip
就是application/zip
。
rar
文件的媒体类型未在IANA上正式注册,但非官方常用的mime-type值为application/x-rar-compressed
。
application/octet-stream
意思是:“我向您发送了文件流,但未指定该流的内容”(因此,它也可以是zip
或rar
文件,这是事实。服务器应该检测流的实际内容是什么。
注意:对于上传,依靠Content-Type
标题中设置的mime类型并不安全。标头是在客户端上设置的,可以设置为任何随机值。相反,您可以使用php文件信息功能来检测服务器上的文件mime类型。
如果要下载zip
文件,则只能设置一个Accept
标头值。如果服务器在Accept
请求的mime-type标头中不能满足您的要求,则设置的任何其他值都将用作备用。
根据WC3规范,此:
application/zip, application/octet-stream
会被解释为:“我更喜欢application/zip
mime类型,但是如果不能提供,则application/octet-stream
(文件流)也可以”。
所以只有一个:
application/zip
将向您保证zip
文件(406 - Not Acceptable
如果服务器无法满足您的请求,则会提供响应)。
您不应信任$_FILES['upfile']['mime']
自己检查MIME类型。为此,您可以使用fileinfo
extension,从PHP 5.3.0开始默认启用。
$fileInfo = new finfo(FILEINFO_MIME_TYPE);
$fileMime = $fileInfo->file($_FILES['upfile']['tmp_name']);
$validMimes = array(
'zip' => 'application/zip',
'rar' => 'application/x-rar',
);
$fileExt = array_search($fileMime, $validMimes, true);
if($fileExt != 'zip' && $fileExt != 'rar')
throw new RuntimeException('Invalid file format.');
注意:不要忘记在您php.ini
的服务器中启用扩展并重新启动服务器:
extension=php_fileinfo.dll
在一个链接的问题中,有一些Objective-C代码来获取文件URL的mime类型。我已经基于Objective-C代码创建了一个Swift扩展来获取mime类型:
import Foundation
import MobileCoreServices
extension URL {
var mimeType: String? {
guard self.pathExtension.count != 0 else {
return nil
}
let pathExtension = self.pathExtension as CFString
if let preferredIdentifier = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, pathExtension, nil) {
guard let mimeType = UTTypeCopyPreferredTagWithClass(preferredIdentifier.takeRetainedValue(), kUTTagClassMIMEType) else {
return nil
}
return mimeType.takeRetainedValue() as String
}
return nil
}
}