使用 Laravel 4 进行文件上传 MIME 类型验证

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21564029/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 08:58:49  来源:igfitidea点击:

File upload mime-type validation with Laravel 4

phpfile-uploadlaravellaravel-4mime-types

提问by ryancey

When I upload a well-formed MP3 file, Laravel 4 tells me it's not audio/mp3but application/octet-stream, which makes this validation fails:

当我上传格式正确的 MP3 文件时,Laravel 4 告诉我它不是audio/mp3but 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/mp3file ?

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

(I already added 'files' => trueto the form declaration)

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

回答by ryancey

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 MimeReaderclass by user Shane, which totally works. I'm still wondering why is it so hard to detect a right mime type though.

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

I implemented it as a validator in Laravel:

我在 Laravel 中实现了它作为验证器:

  • Move MimeReader.phpsin app/libraries/MimeReader.php(watch the extension)
  • Extend the Laravel Validator(I put it in my BaseControllerconstructor)

    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)
  • I can now use audioas a rule ! Example: 'file' => 'required|audio', where filerefers to Input::file('file')
  • 移动MimeReader.phpsapp/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 was considering audio/mpegfiles to be .mpgaand not .mp3. I corrected it in MimeTypeExtensionGuesser.php(in the Symfony library), along with audio/oggthat were considered as .oga. Maybe the audio mime-type depends on what software encoder was used.

Laravel正在考虑audio/mpeg的文件是.mpga.mp3。我在MimeTypeExtensionGuesser.php(在 Symfony 库中)更正了它,audio/ogg并且被认为是.oga. 也许音频 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()Sheikh Heera 所说的那样将 mime 类型直接检查到控制器中。

回答by The Alpha

It's probably because of mp3file's mime type is audio/mpegor could be that, it fails to recognize the mime_content_typeand tells application/octet-streamas a generic/fallback type. You may try this rule (example given below) instead (not tested/sure), because audio/mpegis the correct mime type for mp3according to rfc3003:

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

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

Also, you may manually check the mimetype using something like this:

此外,您可以使用以下内容手动检查mime类型:

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

Update:

更新:

Specially, for mp3files, you may also use a library getID3which is similar to Php PECL extension id3, if you use it, you will be also able to use ID3 tagof the file and can get information such as title, artist, album, year, genreetc.

特别地,对于mp3文件,你也可以使用一个库getID3这是类似PHP的PECL扩展,ID3,如果你使用它,你也将能够使用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 getid3folder from the extracted source into the libsfolder then in your composer.jsonfile add an entry inside classmapof autoloadsection like:

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

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

Then run composer dump-autoloadfrom terminal/command prompt and you are ready to use it. To use it symply try this:

然后composer dump-autoload从终端/命令提示符运行,您就可以使用它了。要使用它 symply 试试这个:

$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 mp3file 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 PECLextension 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 手册