【问题标题】:File upload mime-type validation with Laravel 4使用 Laravel 4 进行文件上传 mime 类型验证
【发布时间】:2014-03-01 02:29:16
【问题描述】:

当我上传格式正确的 MP3 文件时,Laravel 4 告诉我不是 audio/mp3 而是 application/octet-stream,这使得验证失败:

$validator = Validator::make(
    array('trackfile' => Input::file('trackfile')), 
    array('trackfile' => 'required|mimes:mp3')
);

if($validator->fails())
    return 'doesn\'t works because mime type is '.Input::file('trackfile')->getMimeType();
else
    return 'it works!';

为什么不将文件上传为audio/mp3 文件?

(我已经在表单声明中添加了'files' => true

【问题讨论】:

  • 也许看看 vendor\symfony\http-foundation\Symfony\Component\HttpFoundation\File\File.php 会有所帮助。我相信这就是 getMimeType() 所在的地方。
  • array('trackfile' => Input::file('trackfile')) 是什么?
  • @SheikhHeera 将“trackfile”规则键绑定到“trackfile”文件输入。你有什么建议?即使我不确定这是这里的问题!
  • 从规则设置中删除第一行array('trackfile' => Input::file('trackfile')
  • 我必须为验证器指定一个输入,我不能只删除这一行。此外,如果我只输入Input::file('trackfile'),它会告诉我它需要一个数组而不是一个对象。

标签: php file-upload laravel laravel-4 mime-types


【解决方案1】:

编辑

内置验证器仍在将某些 mp3 视为 application/octet-stream,无论您是使用此软件还是那个软件转换了原始文件。

我终于使用了用户ShaneMimeReader 类,它完全有效。不过,我仍然想知道为什么很难检测到正确的 mime 类型。

我在 Laravel 中将其实现为验证器:

  • MimeReader.phps 移入app/libraries/MimeReader.php(观看扩展)
  • 扩展 Laravel Validator(我把它放在我的 BaseController 构造函数中)

    Validator::extend('audio', function($attribute, $value, $parameters)
    {
        $allowed = array('audio/mpeg', 'application/ogg', 'audio/wave', 'audio/aiff');
        $mime = new MimeReader($value->getRealPath());
        return in_array($mime->get_type(), $allowed);
    });
    
  • app/lang/[whatever]/validation.php 中添加您的错误消息(在我的情况下,密钥是audio
  • 我现在可以使用audio 作为一项规则!示例:'file' => 'required|audio',其中file 指的是Input::file('file')

Laravel 将 audio/mpeg 文件视为 .mpga 而不是 .mp3。我在 MimeTypeExtensionGuesser.php(在 Symfony 库中)以及被认为是 .ogaaudio/ogg 中更正了它。也许音频 mime 类型取决于使用的软件编码器。

其他方法是绕过验证器并使用 Input::file('upload')->getMimeType() 直接将 mime-type 检查到控制器中,就像 Sheikh Heera 所说的那样。

【讨论】:

  • +1,很高兴您分享了解决方案,尝试正确描述它,以便为此类问题提供参考。
  • @Shane 的 MimeReader 域已关闭。还有其他地方可以找到吗?
【解决方案2】:

这可能是因为 mp3 文件的 mime 类型是 audio/mpeg 或者可能是因为它无法识别 mime_content_type 并告诉 application/octet-stream 作为通用/后备类型。您可以尝试此规则(下面给出的示例)(未测试/确定),因为根据rfc3003audio/mpegmp3 的正确 mime 类型:

array('trackfile' => 'required|mimes:audio/mpeg,mp3')

另外,您可以使用以下方式手动检查mime 类型:

$file = Input::file('upload');
if($file->getMimeType() == 'audio/mpeg') {
    // valid
}
else {
    // invalid
}

更新:

特别是对于mp3文件,你也可以使用类似于Php PECL extension id3的库getID3,如果你使用它,你也可以使用文件的ID3 tag,并且可以获取信息如titleartistalbumyeargenre

如果你使用它,你必须从给定的链接 (getid3) 手动下载它,并将它放在 app 内的文件夹中,也许是 app/libs/,然后从提取的源中放入 getid3 文件夹进入libs 文件夹,然后在您的composer.json 文件中在classmapautoload 部分中添加一个条目,例如:

// ...
"app/tests/TestCase.php",
"app/libs/getid3"

然后从终端/命令提示符运行composer dump-autoload,您就可以使用它了。要使用它,请尝试以下操作:

$file = Input::file('upload'); // assumed name of the file input is upload
$path = $path = $file->getRealPath();
$id3 = new getID3();
$tags = $id3->analyze($path);
if(is_array($tags) && array_key_exists('audio', $tags)) {
    // valid
    dd($tag['tags']);
}

对于一个有效的mp3 文件,你会得到一个这样的数组:

array (size=2)   'id3v1' => 
    array (size=6)
      'title' => 
        array (size=1)
          0 => string '46. Piya Basanti' (length=16)
      'artist' => 
        array (size=1)
          0 => string '(Freshmaza.com)' (length=15)
      'album' =>
      ...

如果您已经安装或可以使用(从终端)以下命令安装 PECL 扩展:

pear install pecl/id3

那么你可以正常使用

$tags = id3_get_tag( "path/to/example.mp3" );
print_r($tag);

上面的例子会输出类似于:

Array
(
    [title] => DN-38416
    [artist] => Re:\Legion
    [album] => Reflections
    [year] => 2004
    [genre] => 19
)

检查Php manual

【讨论】:

  • 我解决了这个问题。在验证器中指定 audio/mpeg 不起作用,我必须直接在 mime 类型猜测器文件中进行。感谢您抽出宝贵的时间和关于 ID3 标签的额外评论!我一定会调查的。
猜你喜欢
  • 2016-08-05
  • 2017-11-08
  • 2023-03-19
  • 1970-01-01
  • 1970-01-01
  • 2016-08-16
  • 2016-12-28
  • 2015-02-23
  • 2017-06-23
相关资源
最近更新 更多