Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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:

$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 ?

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

like image 839
ryancey Avatar asked Dec 02 '22 17:12

ryancey


1 Answers

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.

I finally used the MimeReader class by user Shane, which totally works. I'm still wondering why is it so hard to detect a right mime type though.

I implemented it as a validator in Laravel:

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

    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 audio as a rule ! Example: 'file' => 'required|audio', where file refers to Input::file('file')

Laravel was considering audio/mpeg files to be .mpga and not .mp3. I corrected it in MimeTypeExtensionGuesser.php (in the Symfony library), along with audio/ogg that were considered as .oga. Maybe the audio mime-type depends on what software encoder was used.

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.

like image 134
ryancey Avatar answered Dec 18 '22 21:12

ryancey