【问题标题】:.rar, .zip files MIME Type.rar, .zip 文件 MIME 类型
【发布时间】:2011-10-22 02:18:02
【问题描述】:

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

我应该使用哪些 MIME 类型来检查 $_FILES[x][type]? (请提供完整列表)

【问题讨论】:

标签: php zip mime-types rar


【解决方案1】:

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

【讨论】:

  • multipart/x-zip 也是 .zip 的有效 mimetype(PKZIP 存档)
  • 其实还有另一种用于 zip 的 MIME TYPE,那就是:application/x-zip-compressed
  • 这根本不能保证你有一个ziprar 文件。根据WC3 specifications,这将被解释为:“我更喜欢application/zip|application/x-rar-compressed 内容类型,但如果你不能提供这个application/octet-stream(文件流)也可以”。我>
  • 这是一个有用的 mime 类型列表,其中包含 .zip 等:sitepoint.com/web-foundations/mime-types-complete-list
  • multipart/x-zip 到底怎么可能是有效的?它不是多部分的。 SitePoint 列表包含许多不准确的 MIME 类型,而且还远未完成。官方IANA Media Types registry 尚未(也可能永远不会)100% 完成。
【解决方案2】:

上传:

可以在The Internet Assigned Numbers Authority (IANA) 找到官方的 mime 类型列表。根据他们的列表,zipContent-Type 标头是 application/zip

rar 文件的媒体类型未在 IANA 正式注册,但非官方常用的 mime-type 值为application/x-rar-compressed

application/octet-stream 的意思是:“我给你发了一个文件流,但没有指定这个流的内容”(所以确实可以是zip 或@ 987654331@ 文件)。服务器应该检测流的实际内容是什么。

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


下载:

如果你想下载一个zip 文件而不是别的,你应该只设置一个Accept 标头值。如果服务器无法满足您在 Accept 标头请求的 mime 类型中的要求,任何附加值设置将用作后备。

根据WC3 specifications这个:

application/zip, application/octet-stream 

将被解释为:“我更喜欢application/zip mime 类型,但如果你不能提供这个application/octet-stream(文件流)也可以”。

所以只有一个:

application/zip

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

【讨论】:

    【解决方案3】:

    您不应该相信$_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
    

    【讨论】:

      【解决方案4】:

      我看到很多关于 zip 和 rar 媒体类型 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

      【讨论】:

      • 嗯,不确定。他们关于 zip 的条目是从 1993 年开始的......
      • @Simpleton 不确定 .zip 是否有 application/zip?不确定我是否对你的观点感兴趣,但如果是这样,为什么标记为官方的媒体类型会随着时间的推移而改变?没有有效期。也许该文件可能会过时。
      • 你是对的,除非它们被新的东西明确地淘汰,否则它们不会过期。但是 IANA 甚至没有提到那些其他的 zip mime 类型。他们来自哪里?它们为什么存在?它们与官方的“应用程序/压缩包”有什么关系?也许 IANA 只是忽略了更新他们的信息?我们如何确定?
      【解决方案5】:

      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
          }
      }
      

      【讨论】:

        【解决方案6】:

        由于扩展名可能包含或多或少三个字符,以下将测试扩展名,无论其长度如何。

        试试这个:

        $allowedExtensions = array( 'mkv', 'mp3', 'flac' );
        
        $temp = explode(".", $_FILES[$file]["name"]);
        $extension = strtolower(end($temp));
        
        if( in_array( $extension, $allowedExtensions ) ) { ///
        

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

        【讨论】:

        • 这很不幸,但不能保证特定操作系统/浏览器组合会遵守其他答案所示的 mime 类型约定。不幸的是,您唯一可以确定的是文件扩展名。
        猜你喜欢
        • 2015-11-01
        • 2014-11-26
        • 2010-10-25
        • 1970-01-01
        • 2014-07-05
        • 2015-01-04
        • 2014-08-09
        • 2012-03-09
        • 1970-01-01
        相关资源
        最近更新 更多