. rar,. zip 文件 MIME 类型

我正在开发一个简单的 php 上传脚本,用户可以上传只有 ZIP 和 RAR 文件。

我应该使用什么 MIME 类型来检查 $_FILES[x][type]? (请提供一个完整的列表)

301648 次浏览

来自自由和平组织,Kiyarash 和 Sam Vloeberghs 的回答:

.rar    application/vnd.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

由于扩展可能包含多于或少于三个字符,下面将测试扩展的长度,而不考虑它的长度。

试试这个:

$allowedExtensions = array( 'mkv', 'mp3', 'flac' );


$temp = explode(".", $_FILES[$file]["name"]);
$extension = strtolower(end($temp));


if( in_array( $extension, $allowedExtensions ) ) { ///

检查最后一个字符之后的所有字符

上载:

官方的默剧类型列表可以在 互联网号码分配局找到。根据他们的列表 Content-Type头为 zipapplication/zip

2016年在 IANA 注册的 rar文件的媒体类型是 application/vnd.rar(参见 https://www.iana.org/assignments/media-types/application/vnd.rar)。Mime-type 值 application/x-rar-compressed在此之前就已经使用过,即使在上面的文档中被标记为不推荐使用,它仍然被广泛使用。

application/octet-stream的意思和 “我给您发送了一个文件流,但没有指定该流的内容”一样(因此它也可以是 ziprar文件)。服务器应该检测流的实际内容是什么。

注意: 对于上传,依赖于 Content-Type头中设置的 mime 类型是不安全的。消息头在客户端上设置,并且可以设置为任意随机值。相反,您可以使用 Php 文件信息函数来检测服务器上的文件 mime-type。


下载:

如果您想下载一个 zip文件,而不想下载其他任何文件,那么您应该只设置一个单独的 Accept头值。如果服务器不能满足您在 Accept头请求的 mime 类型中的要求,那么任何附加值集都将用作备份。

根据 WC3规范的报道:

application/zip, application/octet-stream

将被解释为: “我喜欢一个 ABC0哑剧类型,但如果你不能提供这一个 application/octet-stream(一个文件流)也是罚款”。

所以只有一个:

application/zip

将保证您有一个 zip文件(或者一个 406 - Not Acceptable响应,以防服务器无法满足您的请求)。

您不应该信任 $_FILES['upfile']['mime'],自己检查 MIME 类型。为此,您可以使用 fileinfo分机,默认情况下是从 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
}
}

我看到许多答案报告的压缩和罕见的媒体类型 application/zipapplication/x-rar-compressed,分别。

虽然前者匹配是正确的,但是对于后者,IANA 在这里报告 https://www.iana.org/assignments/media-types/application/vnd.rar,对于 rar application/x-rar-compressed是一个不推荐的别名,而 application/vnd.rar是正式的别名。 因此,2020年来自 IANA 的正确的媒体类型是:

  1. zip: application/zip
  2. rar: application/vnd.rar