Laravel 4 中 File::mime() 的替换(从文件扩展名中获取 mime 类型)

Posted

技术标签:

【中文标题】Laravel 4 中 File::mime() 的替换(从文件扩展名中获取 mime 类型)【英文标题】:Replacement for File::mime() in Laravel 4 (to get mime type from file extension) 【发布时间】:2013-11-10 00:04:23 【问题描述】:

Laravel 3 有一个 File::mime() 方法,可以很容易地从扩展名中获取文件的 mime 类型:

$extension = File::extension($path);
$mime = File::mime($extension);

升级到 Laravel 4 时出现错误:

调用未定义的方法 Illuminate\Filesystem\Filesystem::mime()

我在Filesystem API docs 中也看不到任何提及 mime 类型的内容。

在 Laravel 4 中获取文件 mime 类型的推荐方法是什么(请注意这不是用户上传的文件)?

【问题讨论】:

【参考方案1】:

我发现的一个解决方案是使用Symfony HttpFoundation File class(它已经作为依赖项包含在 Laravel 4 中):

$file = new Symfony\Component\HttpFoundation\File\File($path);
$mime = $file->getMimeType();

事实上 File 类使用 Symfony MimeTypeGuesser 类所以这也有效:

$guesser = Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesser::getInstance();
echo $guesser->guess($path);

但不幸的是,我得到了意想不到的结果:将路径传递给 css 文件时,我得到的是 text/plain 而不是 text/css

【讨论】:

从relatedquestions看来,这不是一个可靠的方法。 文本/纯文本而不是大量其他格式也存在同样的问题。 js、txt、xls、po 等 - 都得到文本/纯 mimes【参考方案2】:

如果您刚刚上传了可以使用的文件:

Input::file('field_name')->getMimeType();

你可以看到更多here!我希望它会有所帮助! :D

编辑:Input::fileFile 的某种扩展,因此您也可以使用File::get('file')->getMimeType();。未测试,但必须有效。

【讨论】:

谢谢,但如前所述,我想将其用于任何常规文件,而不是刚刚上传的文件。 谢谢。但是 File::get() 返回一个字符串,所以不能调用 getMimeType()。此外,Symfony 的 getMimeType() 对于我需要它工作的 CSS 文件类型并不可靠(请参阅我自己的答案)。 是的,我猜这似乎是 Laravel 的一个错误。你看过 Laravel 的 GitHub 仓库吗?你应该看看问题跟踪,看看你是否发现了什么! 那个方法不可靠。结果毫无用处。【参考方案3】:

看完之后:

php mime_content_type() 已弃用 它的替代品FileInfo不可靠 Symfony 的 getMimeType() 使用 FileInfo(请参阅我的其他答案)

我决定将 Laravel 3 的 File::mime() 实现移植到我的 Laravel 4 应用程序中的帮助程序库中。 Laravel 3 实现只是根据文件扩展名从配置查找数组中读取 MIME 类型。

解决方案:

application/config/mimes.php 从我的 L3 项目复制到 app/config/mimes.php 在我的 L4 项目中 使用 Laravel 3 File class 中的 File::mime() 函数代码制作了一个 FileHelper 库。

【讨论】:

【参考方案4】:

原来 Symfony ExtensionGuesserMimeTypeGuesser 使用了不可靠的 FileInfo 类。因此,对 mime 的验证会返回不可预测的结果,并且不能以正确的方式用于文件上传(它会返回 text/plain mime for jsxlspo 等)。

我已经为这个问题找到了非常简单的解决方案。

代替

'attachment' => 'required|mimes:jpg,jpeg,bmp,png,doc,docx,zip,rar,pdf,rtf,xlsx,xls,txt|max:10000',

我把它分成两个不同的部分,现在我的验证看起来像这样:

private function createFileAttachmentValidator($file)

    return Validator::make(
        [
            'attachment' => $file,
            'extension'  => \Str::lower($file->getClientOriginalExtension()),
        ],
        [
            'attachment' => 'required|max:10000',
            'extension'  => 'required|in:jpg,jpeg,bmp,png,doc,docx,zip,rar,pdf,rtf,xlsx,xls,txt',
        ],
        $this->validationMessages()
    );          
   

我只是尝试验证文件的扩展名是否存在以及它是否列在我的in 规则中。这行得通,但是,解决方案并不完美。

【讨论】:

将其与内置的 mime 验证一起使用是解决此问题的最佳方法。【参考方案5】:
public function mimeType($path)

    return finfo_file(finfo_open(FILEINFO_MIME_TYPE), $path);

参考:https://github.com/illuminate/filesystem/blob/master/Filesystem.php#L194

【讨论】:

以上是关于Laravel 4 中 File::mime() 的替换(从文件扩展名中获取 mime 类型)的主要内容,如果未能解决你的问题,请参考以下文章

如何更改文件 mime 类型以绕过 php shell 上传? [关闭]

Rails 3 回形针 mime 类型 - Office 2007

AWS 预签名 URL

[php]强制下载文件

Laravel 4 从 URL 中删除公共

Laravel 4 - 将 json 解码到视图中