【问题标题】:Is MIME type detection the best way to detect a kind of file?MIME 类型检测是检测一种文件的最佳方法吗?
【发布时间】:2012-04-21 01:42:35
【问题描述】:

我正在使用 PHP 制作一个只能允许 MP3 文件的上传表单。

上传完成后,我会分析文件以检查它是否真的是 MP3。第一步是检测 mime 类型为audio/mpeg。我使用库 finfo_file() 并且工作正常,只是在测试期间某些 MP3 文件被拒绝,因为它们的 MIME 类型结果为 application/octet-stream

我的问题是:

  • 我的应用程序应该绝对拒绝那些 MP3 文件吗?他们实际上是在播放音频。
  • 这个 MIME 类型是 MP3 有什么原因吗?
  • 检测 MIME 类型是了解文件类型的最可靠方法吗?

【问题讨论】:

    标签: php mp3 mime-types


    【解决方案1】:

    如果您想要一种极其可靠的文件类型检测方法,而不仅仅信任客户端提供正确的 MIME 类型,请在 UNIX 上使用 file 实用程序。

    $ file Black\ Sands\ 01\ Prelude.mp3
    Black Sands 01 Prelude.mp3: Audio file with ID3 version 2.2.0, contains: MPEG ADTS, layer III, v1, 320 kbps, 44.1 kHz, Stereo
    
    $ file homework/math475-hw8.docx
    homework/math475-hw8.docx: Microsoft Word 2007+
    

    在 PHP 中,您可以使用 exec 函数来调用它。

    【讨论】:

    • 这是一个我没有考虑过的选项.. 我无法测试,因为我在赢
    • 有一个为win32编译的版本here
    • file 命令和 PHP 的 finfo_file 函数使用相同的方法来确定 mime 类型(通常通过引用 /usr/share/misc/magic)。当你有一个内置函数时,exec file 是没有用的。但是,我有一个案例,finfo_filefile -I 都将.mp3 检测为application/octet-stream,而我希望它返回audio/mpeg。两者都失败了。但是,我认为这可以通过将改进的magic 文件的路径作为finfo_open 的第二个参数传递来解决。
    【解决方案2】:

    除了 MIME 之外,最好的文件检测方法是使用“magic byte”或“magic number”方案。 Unix file(以及finfo_file)实际上使用“魔术字节”来执行此文件检测。所以,简而言之:是的。

    不要太担心您的文件是什么样子,而更多地关心您可以用它做什么。只要能播放,文件应该没问题。

    如果您真的想要做更多,您可以自己检查魔术字节。有a list of them here

    【讨论】:

    • 这就是为什么使用 getid3() 类我得到“audio/mpeg”但使用 finfo_filei 在同一个文件上得到“application/octet-stream”.. 这有点奇怪.. 但即使文件是可播放的,如果结果具有不同的 mime 类型,出于安全原因它将被拒绝(除非我找到更好的方法).. 我想知道有多少 mp3 没有正确的 mime..
    • @enkore “我想知道有多少 mp3 没有正确的 mime” MIME 类型由客户端提供。它不是 mp3 文件本身固有的。
    【解决方案3】:

    在大多数需要上传的应用程序中,我有时会根据预定义的 MIME 类型列表验证浏览器(客户端)传递的 MIME。这种方法一般假设如果发生了一些可疑的事情,而浏览器无法传达正在上传的文件的 MIME 类型,我现在可能不想费心处理它。

    <?php
    
    $valid_mp3_mimes = array(
        'audio/mpeg',
        'audio/x-mpeg',
        'audio/mp3',
        'audio/x-mp3',
        'audio/mpeg3',
        'audio/x-mpeg3',
        'audio/x-mpeg-3',
        'audio/mpg',
        'audio/x-mpg',
        'audio/x-mpegaudio',
        'video/mpeg',
        'video/x-mpeg',
    );
    
    $uploaded_file_mime = $_FILES['upload_field_name']['type'];
    
    if(!in_array($uploaded_file_mime, $valid_mp3_mimes))
    {
        die('Upload is not a valid MP3 file.');
    }
    

    您可能会或可能不会觉得这足以满足您的目的。 PHP 手册明确指出,如果浏览器提供此信息,此信息可用,并且 MIME 类型未在服务器端检查,因此不应视为理所当然。

    要考虑的一件事是服务器上允许您验证文件的真正 MIME 类型的资源的可用性。

    作为 PHP 开发人员,我们喜欢在大多数情况下创建独立于平台的代码的灵活性(例如,我们在运行 XAMPP 的 Windows 系统上构建的 Web 应用程序可以部署到 Linux 托管环境,只需很少的修改)。但是,在验证 MIME 类型时,我们开始引入需要验证这些工具是否存在的平台相关方法(例如“file”或“finfo_file”)。

    这可能是一个值得研究的实现(取自 CodeIgniter GitHub 存储库),它利用了这些工具,并且与 PHP 范围内的工作示例一样完整:

    如果可能,文件 MIME 类型会检测上传文件的(实际)MIME 类型。 https://github.com/EllisLab/CodeIgniter/blob/develop/system/libraries/Upload.php#L983


    来源

    PHP 手册 POST 方法上传 - http://www.php.net/manual/en/features.file-upload.post-method.php

    网站管理员工具包 Mime 类型 - http://www.webmaster-toolkit.com/mime-types.shtml

    FILExt .MP3 文件 - http://filext.com/file-extension/MP3

    【讨论】:

      猜你喜欢
      • 2012-10-14
      • 2017-09-08
      • 2018-08-20
      • 2011-06-19
      • 2011-12-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-09
      • 2011-02-17
      相关资源
      最近更新 更多