乐趣区

关于php:学习PHP中Fileinfo扩展的使用

明天来学习的这个扩大其实当初也曾经是标配的一个扩大了,为什么呢?因为 Laravel 框架在装置的时候它就是必须的一个扩大,没有关上它的话,连 Laravel 框架都是无奈应用的。

Fileinfo 介绍

Fileinfo 是通过给定的 magic 字节序列库来取得文件的内容类型及编码。它所获取的序列库是依据操作系统来定的,比方在 Linux 零碎中默认应用的就是 /usr/share/misc/magic 这个文件。其实咱们就是能够用这个扩大的函数来取得文件的 MIME 信息,就像咱们常见的 image/png、text/html 这些内容。

Fileinfo 这个扩大也是为了兼容新老开发模式,所以提供了面向过程和面向对象的两种模式,咱们先来看看面向对象的模式如何应用。

面向对象应用

$finfo = new finfo(FILEINFO_MIME);

echo $finfo->file("./1.PHP 中的日期相干函数(三).php"), PHP_EOL;
// text/x-php; charset=us-ascii


echo $finfo->buffer(file_get_contents("https://www.baidu.com")) . "\n";
// text/html; charset=utf-8

$finfo->set_flags(FILEINFO_EXTENSION);
echo $finfo->file('timg.jpeg') . "\n";
// jpeg/jpg/jpe/jfif

首先,咱们通过 new 一个 finfo 类来取得文件操作对象,参数中的常量是可选的,默认状况下是 FILEINFO_NONE,代表无非凡解决,这里咱们应用的是 FILEINFO_MIME 表明依照 RFC2045 定义的格局返回文件 mime 类型和编码。

而后应用 file() 办法,就能够取得指定文件的 mime 信息了。buffer() 办法则是返回字符串内容的信息,比方咱们获取一个网页信息的内容,就可能失去它的字符串代表的文件编码格局为 text/hmtl。set_flags() 办法是能够在实例化对象之后批改它的结构参数属性,也就是咱们在实例化时设置的那个参数信息,在这里咱们将它批改为 FILEINFO_EXTENSION,也就是让 finfo 对象返回文件可能的扩展名。咱们应用一张图片进行测试,返回的可能扩展名就包含正文中展现的这些。

面向过程

针对下面面向对象的代码,咱们也展现一下雷同的操作应用面向过程的函数是如何运行的。

$finfo = finfo_open(FILEINFO_MIME);
echo finfo_file($finfo,"./1.PHP 中的日期相干函数(三).php"), PHP_EOL;
// text/x-php; charset=us-ascii

echo finfo_buffer($finfo, file_get_contents("https://www.baidu.com")), PHP_EOL;
// text/html; charset=utf-8

finfo_set_flags($finfo, FILEINFO_EXTENSION);
echo finfo_file($finfo, 'timg.jpeg') . "\n";
// jpeg/jpg/jpe/jfif

finfo_close($finfo);

能够看出,这里就是将 finfo 对象换成了 finfo_open() 办法来取得一个 finfo 操作句柄。之后应用相似的 finfo_file()、finfo_buffer()、finfo_set_flags() 函数来进行操作,实现的成果和下面的面向对象的后果是一样的。

须要留神的,面向过程的写法是有一个 finfo_close() 办法的,个别对于句柄类型的操作都会有一个敞开的函数来开释句柄资源。就像 mysqli 之类的扩大一样,finfo 中也是蕴含一个这样的函数的,并且只提供面向过程的这个函数,下面的 finfo 类中是没有这样一个 close() 办法的。

疾速返回 mime

当然,Fileinfo 扩大也为咱们提供了一个疾速地返回文件 mime 信息的函数。咱们能够不必应用 finfo 对象或者关上一个 finfo 句柄就能够方便快捷地取得一个文件的 mime 信息。

echo mime_content_type('./1.PHP 中的日期相干函数(三).php'), PHP_EOL;
// text/x-php

echo mime_content_type('./timg.jpeg'), PHP_EOL;
// image/jpeg

不过 PHP 官网仿佛废除过这个函数,但当初又复原了它,也就是说并不是特地的举荐应用这个函数。在正式的开发过程中,咱们还是不要嫌麻烦,应用 finfo 对象或者 finfo 相干的函数来取得 mime 信息会更靠谱一些。

如果咱们确定要判断的文件只是图片类型的话,那么咱们还能够用另外一个函数来进行图片文件的 mime 获取。

$image = exif_imagetype("./timg.jpeg"); 
echo image_type_to_mime_type($image), PHP_EOL;
// image/jpeg

总结

非常简单然而很实用的函数,为什么说它实用呢?上传文件的安全性问题就能够靠它来解决。咱们在上传文件的时候,通常会判断文件的后缀名及上传数组中的文件 MIME 类型。不过很多工具是能够在上传过程中批改文件的 MIME 类型的,也就是通过一些抓包工具批改 Content-Type。而通过 Fileinfo 扩大取得必须是本地或近程曾经存在的文件,也就是说不会有上传过程中因为批改传输信息而产生的安全检查绕过问题。

因而,在 Lavarl 框架中,vendor/laravel/framework/src/Illuminate/Filesystem/Filesystem.php 类中的 mimeType() 办法应用的正是 finfo_file() 这个函数来获取文件的 mime 信息。在它的上传组件中,Laravel 的底层 symfony 框架中,对于上传文件的 MIME 判断也是应用的 finfo_file() 函数,(vendor/symfony/mime/FileinfoMimeTypeGuesser.php) 并没有间接应用失常的上传后的 $_FILES 中的 type 字段。

测试代码:

https://github.com/zhangyue0503/dev-blog/blob/master/php/202010/source/5. 学习 PHP 中 Fileinfo 扩大的应用.php

参考文档:

https://www.php.net/manual/zh/book.fileinfo.php

===========

各自媒体平台均可搜寻【硬核项目经理】

退出移动版