Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel 5 Mime validation

Ok, I'm trying to upload a video, and validate the file type.

According to the documentation:

mimes:foo,bar,...

The file under validation must have a MIME type corresponding to one of the listed extensions.

Basic Usage Of MIME Rule

'photo' => 'mimes:jpeg,bmp,png'

I'm uploading a wmv video, and my rules are so:

return [
    'file' => ['required', 'mimes:video/x-ms-wmv']
]

I've done a print_r() on Request::file('file') and I get the following data:

Symfony\Component\HttpFoundation\File\UploadedFile Object
(
    [test:Symfony\Component\HttpFoundation\File\UploadedFile:private] => 
    [originalName:Symfony\Component\HttpFoundation\File\UploadedFile:private] => SampleVideo.wmv
    [mimeType:Symfony\Component\HttpFoundation\File\UploadedFile:private] => video/x-ms-wmv
    [size:Symfony\Component\HttpFoundation\File\UploadedFile:private] => 70982901
    [error:Symfony\Component\HttpFoundation\File\UploadedFile:private] => 0
    [pathName:SplFileInfo:private] => C:\wamp\tmp\php6428.tmp
    [fileName:SplFileInfo:private] => php6428.tmp
)

However I'm getting the error:

{"file":["The file must be a file of type: video\/x-ms-wmv."]}

I've tried changing the "mime type" to video/*, wmv (as per the docs) and also video/x-ms-wmv yet none of them validate the file correctly.

As you can see from the print_r() the mime type Symfony is getting is video/x-ms-wmv.

Am I doing something wrong? Or can Laravel/Symfony just not validate files well?

I appreciate the help

Edit Ok, I opened validator.php and added echo $value->guessExtension(); to the ValidateMimes() method, and it outputs asf.

Why is Symfony outputting video\x-ms-wmv, the file extension is wmv, I'm validating both of them, but Laravel is guessing asf?!

It's too unreliable for video validation for me.

like image 575
Phil Cross Avatar asked Apr 24 '15 08:04

Phil Cross


1 Answers

This is expected behaviour.

Laravel is calling guessExtension on Symphony's UploadedFile object, which will return the expected extension of the file, not the mimetype.

This is why the documenatation states that for an uploaded image you should use:

'photo' => 'mimes:jpeg,bmp,png'

Symfony's guessExtension calls getMimeType, which uses PHP's Fileinfo Functions to go and guess the mimetype of a given file.

Once getMimeType guesses the mimetype for the file, Symfony's MimeTypeExtensionGuesser kicks in to get the extension from the mime type retrieved from a file.

    // ... cut from MimeTypeExtensionGuesser
    'video/x-ms-asf' => 'asf',
    'video/x-ms-wmv' => 'wmv',
    'video/x-ms-wmx' => 'wmx',
    'video/x-ms-wvx' => 'wvx',
    'video/x-msvideo' => 'avi',

Therefore, your rules should be:

return [
    'file' => ['required', 'mimes:wmv,asf']
]

The reason that asf should be included is mainly historical. To quote Wikipedia:

The most common media contained within an ASF file are Windows Media Audio (WMA) and Windows Media Video (WMV). The most common file extensions for ASF files are extension .WMA (audio-only files using Windows Media Audio, with MIME-type 'audio/x-ms-wma') and .WMV (files containing video, using the Windows Media Audio and Video codecs, with MIME-type 'video/x-ms-asf'). These files are identical to the old .ASF files but for their extension and MIME-type.

Microsoft's documentation about the difference between ASF and WMV/WMA files states:

The only difference between ASF files and WMV or WMA files are the file extensions and the MIME types [...] The basic internal structure of the files is identical.

Because the internal structure of the file is identical (including the magic numbers for the file format), wmv, wma and asf are one and the same. The only difference between the three extensions is the icon that is shown inside Explorer.

It's not just Windows Media files that will have this issue, Wikipedia lists many different video container formats that will have the same problem. If you want to find the video codec that is being used in a container, you are going to need to look at more then just the "magic patterns" that are used by the fileinfo functions.


That being said, expected behaviour != correct behaviour.

I submitted a pull request to add a new validator, called mimetypes. This does as you would expect and uses the guessed mimetype to validate an uploaded file, instead of the extension that is guessed from the mimetype.

like image 123
Tim Groeneveld Avatar answered Nov 09 '22 10:11

Tim Groeneveld