简体   繁体   English

使用Laravel 4文件上传mime类型验证

[英]File upload mime-type validation with Laravel 4

When I upload a well-formed MP3 file, Laravel 4 tells me it's not audio/mp3 but application/octet-stream , which makes this validation fails: 当我上传格式良好的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!';

Why doesn't it upload the file as an audio/mp3 file ? 为什么不将文件上传为audio/mp3文件?

(I already added 'files' => true to the form declaration) (我已经在表单声明中添加了'files' => true

Edit 编辑

Built-in validator was still considering some mp3's as application/octet-stream, wether you converted the original file with this or that software. 内置验证器仍在考虑使用某些mp3作为应用程序/八位字节流,您是否使用此软件转换原始文件。

I finally used the MimeReader class by user Shane , which totally works. 我终于使用了用户ShaneMimeReader类,它完全有效。 I'm still wondering why is it so hard to detect a right mime type though. 我仍然想知道为什么如此难以检测到正确的mime类型。

I implemented it as a validator in Laravel: 我在Laravel中将其实现为验证器:

  • Move MimeReader.phps in app/libraries/MimeReader.php (watch the extension) app/libraries/MimeReader.php移动MimeReader.phps (观看扩展名)
  • Extend the Laravel Validator (I put it in my BaseController constructor) 扩展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); }); 
  • Add your error message in app/lang/[whatever]/validation.php (in my case, the key is audio ) app/lang/[whatever]/validation.php添加错误信息(在我的情况下,键是audio
  • I can now use audio as a rule ! 我现在可以使用audio了! Example: 'file' => 'required|audio' , where file refers to Input::file('file') 示例: 'file' => 'required|audio' ,其中file引用Input::file('file')

Laravel was considering audio/mpeg files to be .mpga and not .mp3 . Laravel正在考虑将audio/mpeg文件设为.mpga而不是.mp3 I corrected it in MimeTypeExtensionGuesser.php (in the Symfony library), along with audio/ogg that were considered as .oga . 我在MimeTypeExtensionGuesser.php (在Symfony库中)以及被认为是.oga audio/ogg中更正了它。 Maybe the audio mime-type depends on what software encoder was used. 也许音频mime类型取决于使用的软件编码器。

Other method is to bypass the validator and check the mime-type directly into the controller using Input::file('upload')->getMimeType() like Sheikh Heera said. 其他方法是绕过验证器并使用Input::file('upload')->getMimeType()直接将mime-type检查到控制器中,如Sheikh Heera所说。

It's probably because of mp3 file's mime type is audio/mpeg or could be that, it fails to recognize the mime_content_type and tells application/octet-stream as a generic/fallback type. 这可能是因为mp3文件的mime类型是audio/mpeg或者可能是因为它无法识别mime_content_type并将application/octet-stream告知为通用/后备类型。 You may try this rule (example given below) instead (not tested/sure), because audio/mpeg is the correct mime type for mp3 according to rfc3003 : 您可以尝试此规则(下面给出的示例)(未测试/确定),因为根据rfc3003audio/mpegmp3的正确mime类型:

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

Also, you may manually check the mime type using something like this: 此外,您可以使用以下方法手动检查mime类型:

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

Update: 更新:

Specially, for mp3 files, you may also use a library getID3 which is similar to Php PECL extension id3 , if you use it, you will be also able to use ID3 tag of the file and can get information such as title , artist , album , year , genre etc. 特别是,对于mp3文件,你也可以使用类似于Php PECL扩展id3的库getID3 ,如果你使用它,你也可以使用文件的ID3 tag ,并且可以获得titleartistalbumyeargenre

If you use it, you have to download it manually from the given link ( getid3 ) and put it in a folder inside app , maybe app/libs/ and just put the getid3 folder from the extracted source into the libs folder then in your composer.json file add an entry inside classmap of autoload section like: 如果您使用它,您必须从给定的链接( getid3 )手动下载并将其放在app内的文件夹中,也许是app/libs/ ,然后将提取的源中的getid3文件夹放入libs文件夹,然后放入composer.json文件里面添加一个条目classmapautoload状部分:

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

Then run composer dump-autoload from terminal/command prompt and you are ready to use it. 然后从终端/命令提示符运行composer dump-autoload ,您就可以使用它了。 To use it symply try this: 要使用它,请尝试以下方法:

$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']);
}

For a valid mp3 file You'll get an array like this: 对于有效的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' =>
      ...

If you have already installed or can install the PECL extension using (from terminal) following command: 如果您已经安装或可以使用(从终端)以下命令安装PECL扩展:

pear install pecl/id3

Then you may normally use 那你通常可以使用

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

The above example will output something similar to: 上面的例子将输出类似于:

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

Check Php manual . 检查Php手册

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM