Laravel 5 Mime 验证
Posted
技术标签:
【中文标题】Laravel 5 Mime 验证【英文标题】:Laravel 5 Mime validation 【发布时间】:2015-07-02 18:29:55 【问题描述】:好的,我正在尝试上传视频,并验证文件类型。
根据文档:
mimes:foo,bar,...
正在验证的文件必须具有与列出的扩展名之一相对应的 MIME 类型。
MIME 规则的基本用法
'照片' => 'mimes:jpeg,bmp,png'
我正在上传一个 wmv 视频,我的规则是这样的:
return [
'file' => ['required', 'mimes:video/x-ms-wmv']
]
我在Request::file('file')
上做了一个print_r()
,我得到了以下数据:
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
)
但是我得到了错误:
"file":["The file must be a file of type: video\/x-ms-wmv."]
我尝试将“mime 类型”更改为 video/*
、wmv
(根据文档)以及 video/x-ms-wmv
,但它们都没有正确验证文件。
从print_r()
中可以看出,Symfony 的 MIME 类型变得是 video/x-ms-wmv
。
我做错了吗?或者 Laravel/Symfony 不能很好地验证文件?
感谢您的帮助
编辑
好的,我打开validator.php
并在ValidateMimes()
方法中添加了echo $value->guessExtension();
,它输出了asf。
为什么 Symfony 输出 video\x-ms-wmv
,文件扩展名是 wmv,我正在验证它们,但 Laravel 猜测 asf
?!
视频验证对我来说太不可靠了。
【问题讨论】:
我也遇到了这个问题,问题出在我使用的 PHP 版本上,尝试创建一个 vanilla php 文件并使用 Fileinfo 函数检查视频的 mime 类型php.net/manual/en/book.fileinfo.php 【参考方案1】:这是预期的行为。
Laravel is 在 Symphony 的 UploadedFile 对象上调用 guessExtension
,这将返回文件的预期扩展名,而不是 mimetype。
这就是为什么文档说明您应该使用上传的图片:
'照片' => 'mimes:jpeg,bmp,png'
Symfony 的 guessExtension
调用 getMimeType
,它使用 PHP 的 Fileinfo Functions 去猜测给定文件的 mimetype。
一旦getMimeType
猜测文件的mimetype,Symfony 的MimeTypeExtensionGuesser 就会从文件中检索的mime 类型中获取扩展名。
// ... 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',
因此,您的规则应该是:
return [
'file' => ['required', 'mimes:wmv,asf']
]
应该包含asf
的原因主要是历史原因。引用***:
ASF 文件中最常见的媒体是 Windows Media Audio (WMA) 和 Windows Media Video (WMV)。 ASF 文件最常见的文件扩展名是扩展名 .WMA(使用 Windows Media Audio 的纯音频文件,MIME 类型为“
audio/x-ms-wma
”)和 .WMV(包含视频的文件,使用 Windows Media 音频和视频编解码器,使用MIME 类型“video/x-ms-asf
”)。这些文件与旧的 .ASF 文件相同,但扩展名和 MIME 类型不同。
Microsoft 的文档关于 the difference between ASF and WMV/WMA files 状态:
ASF 文件与 WMV 或 WMA 文件之间的唯一区别是文件扩展名和 MIME 类型 [...] 文件的基本内部结构是相同的。
因为文件的内部结构是相同的(包括文件格式的magic numbers),所以wmv、wma和asf是一回事。这三个扩展程序之间的唯一区别是在 Explorer 中显示的图标。
不仅仅是 Windows Media 文件会出现此问题,Wikipedia lists 许多不同的视频容器格式也会出现同样的问题。如果您想查找容器中使用的视频编解码器,您需要查看的不仅仅是 fileinfo
函数使用的 "magic patterns"。 p>
话虽如此,预期的行为!= 正确的行为。
我提交了一个pull request 来添加一个名为mimetypes
的新验证器。这正如您所期望的那样,并使用猜测的 mimetype 来验证上传的文件,而不是从 mimetype 中猜测的扩展名。
【讨论】:
感谢您的解释,您知道我是否只是不幸选择了“困难”文件类型(wmv/asf),还是其他文件类型也会出现这种情况(也就是说,我希望它是 mp4,但它“猜测”另一个扩展名,例如)? @PhilCross,主要是 WMV/ASF 有这个问题。 mp4 经历了一个更好的标准化过程 :) (虽然,您可能仍然会遇到 .mpv 文件被标记为 mp4 等的问题,但这是可以预料的 - 即,您希望将jpeg
文件标记为 @ 987654343@等)。 wmv
的问题在于它是一个容器格式,就像mkv
一样,所以仅仅因为它最后有“.wmv”,并不意味着它确实使用Windows Media Video
格式。
感谢您的再次解释!我会 +1 答案:)
Laravel 中的字体怎么样?我对字体使用请求验证,但它不起作用! 'fontwoff2colum' => 'mimes:woff2'
@FaridVatani mimetype应该是application/font-woff
。见github.com/symfony/mime/blob/master/MimeTypes.php以上是关于Laravel 5 Mime 验证的主要内容,如果未能解决你的问题,请参考以下文章
Laravel 可以验证 markdown mime 类型吗?