我正在开发一个简单的php上传脚本,用户只能上传ZIP和RAR文件。
我应该使用哪些MIME类型来检查$_FILES[x][type]
? (请完整清单)
谢谢..
答案 0 :(得分:218)
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
答案 1 :(得分:29)
可以在The Internet Assigned Numbers Authority (IANA) 找到正式的哑剧类型列表。根据{{1}}的{{1}}标题Content-Type
标题为zip
。
application/zip
文件的媒体类型未在IANA正式注册,但非官方常用的mime类型值为rar
。
application/x-rar-compressed
意味着:&#34;我向您发送了一个文件流,并且未指定此流的内容&#34; (所以它确实可以也是application/octet-stream
或zip
文件。服务器应该检测流的实际内容是什么。
注意:对于上传,依赖rar
标头中设置的mime类型是不安全的。标头在客户端上设置,可以设置为任意随机值。相反,您可以使用the php file info函数来检测服务器上的文件mime-type。
如果您要下载Content-Type
文件,则不应该只设置一个zip
标头值。如果服务器无法满足Accept
标头请求的mime类型,则任何其他值都将用作后备。
根据WC3 specifications这个:
Accept
将被定义为:&#34;我更喜欢application/zip, application/octet-stream
mime-type,但是如果你不能提供这个,application/zip
(文件流)也很好&#34; 的
所以只有一个:
application/octet-stream
如果服务器无法满足您的请求,将保证application/zip
文件(或zip
响应。)
答案 2 :(得分:4)
您不应该信任if(isset($_GET['delete']))
,请自行检查MIME类型。为此,您可以使用fileinfo
extension,默认情况下从PHP 5.3.0开始启用。
$_FILES['upfile']['mime']
注意:不要忘记在 $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
答案 3 :(得分:0)
在a linked question中,有一些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
}
}
答案 4 :(得分:0)
我看到许多针对zip和rar媒体类型application/zip
和application/x-rar-compressed
的答案报告。
虽然前一种匹配是正确的,但对于后者的IANA报告https://www.iana.org/assignments/media-types/application/vnd.rar来说,rar application/x-rar-compressed
是弃用的别名,而application/vnd.rar
是正式名称。
因此,2020年IANA的正确媒体类型为:
zip
:application/zip
rar
:application/vnd.rar
答案 5 :(得分:-2)
由于扩展名可能包含多于或少于三个字符,因此无论其长度如何,以下内容都将测试扩展名。
试试这个:
$allowedExtensions = array( 'mkv', 'mp3', 'flac' );
$temp = explode(".", $_FILES[$file]["name"]);
$extension = strtolower(end($temp));
if( in_array( $extension, $allowedExtensions ) ) { ///
检查最后一个'。'
之后的所有字符