PHP Conference Japan 2024

finfo_file

finfo::file

(PHP >= 5.3.0, PHP 7, PHP 8, PECL fileinfo >= 0.1.0)

finfo_file -- finfo::file返回有关文件的信息

描述

过程式风格

finfo_file(
    finfo $finfo,
    string $filename,
    int $flags = FILEINFO_NONE,
    ?resource $context = null
): string|false

面向对象风格

public finfo::file(string $filename, int $flags = FILEINFO_NONE, ?resource $context = null): string|false

此函数用于获取有关文件的信息。

参数

finfo

一个 finfo 实例,由 finfo_open() 返回。

filename

要检查的文件名。

flags

一个或多个 Fileinfo 常量 的组合。

context

有关 contexts 的描述,请参阅 流函数

返回值

返回 filename 参数内容的文本描述,如果发生错误则返回 false

变更日志

版本 描述
8.1.0 finfo 参数现在需要一个 finfo 实例;以前需要一个 resource
8.0.0 context 现在可以为空。

范例

示例 #1 一个 finfo_file() 示例

<?php
$finfo
= finfo_open(FILEINFO_MIME_TYPE); // 返回 mime 类型,也就是 mimetype 扩展名
foreach (glob("*") as $filename) {
echo
finfo_file($finfo, $filename) . "\n";
}
finfo_close($finfo);
?>

以上示例将输出类似以下内容

text/html
image/gif
application/vnd.ms-excel

参见

添加注释

用户贡献的注释 12 条注释

Schraalhans Keukenmeester
17 年前
虽然使用 finfo_file() 验证上传的图像文件(检查所谓的图像文件是否真的包含图像)似乎很诱人,但结果并不可靠。例如,将有害的可执行代码封装在一个被识别为 GIF 的文件中并不难。

更好更安全的选项是检查以下结果:

if (!$img = @imagecreatefromgif($uploadedfilename)) {
trigger_error('Not a GIF image!',E_USER_WARNING);
// 执行必要的操作
}
66Ton99 at gmail dot com
8 年前
如何获取远程文件的 MIME 类型。

<?php
class MimeStreamWrapper
{
const
WRAPPER_NAME = 'mime';
public
$context;
private static
$isRegistered = false;
private
$callBackFunction;
private
$eof = false;
private
$fp;
private
$path;
private
$fileStat;
private function
getStat()
{
if (
$fStat = fstat($this->fp)) {
return
$fStat;
}

$size = 100;
if (
$headers = get_headers($this->path, true)) {
$head = array_change_key_case($headers, CASE_LOWER);
$size = (int)$head['content-length'];
}
$blocks = ceil($size / 512);
return array(
'dev' => 16777220,
'ino' => 15764,
'mode' => 33188,
'nlink' => 1,
'uid' => 10000,
'gid' => 80,
'rdev' => 0,
'size' => $size,
'atime' => 0,
'mtime' => 0,
'ctime' => 0,
'blksize' => 4096,
'blocks' => $blocks,
);
}
public function
setPath($path)
{
$this->path = $path;
$this->fp = fopen($this->path, 'rb') or die('无法打开文件: ' . $this->path);
$this->fileStat = $this->getStat();
}
public function
read($count) {
return
fread($this->fp, $count);
}
public function
getStreamPath()
{
return
str_replace(array('ftp://', 'http://', 'https://'), self::WRAPPER_NAME . '://', $this->path);
}
public function
getContext()
{
if (!
self::$isRegistered) {
stream_wrapper_register(self::WRAPPER_NAME, get_class());
self::$isRegistered = true;
}
return
stream_context_create(
array(
self::WRAPPER_NAME => array(
'cb' => array($this, 'read'),
'fileStat' => $this->fileStat,
)
)
);
}
public function
stream_open($path, $mode, $options, &$opened_path)
{
if (!
preg_match('/^r[bt]?$/', $mode) || !$this->context) {
return
false;
}
$opt = stream_context_get_options($this->context);
if (!
is_array($opt[self::WRAPPER_NAME]) ||
!isset(
$opt[self::WRAPPER_NAME]['cb']) ||
!
is_callable($opt[self::WRAPPER_NAME]['cb'])
) {
return
false;
}
$this->callBackFunction = $opt[self::WRAPPER_NAME]['cb'];
$this->fileStat = $opt[self::WRAPPER_NAME]['fileStat'];

return
true;
}
public function
stream_read($count)
{
if (
$this->eof || !$count) {
return
'';
}
if ((
$s = call_user_func($this->callBackFunction, $count)) == '') {
$this->eof = true;
}
return
$s;
}
public function
stream_eof()
{
return
$this->eof;
}
public function
stream_stat()
{
return
$this->fileStat;
}
public function
stream_cast($castAs)
{
$read = null;
$write = null;
$except = null;
return @
stream_select($read, $write, $except, $castAs);
}
}
$path = 'http://fc04.deviantart.net/fs71/f/2010/227/4/6/PNG_Test_by_Destron23.png';
echo
"文件: ", $path, "\n";
$wrapper = new MimeStreamWrapper();
$wrapper->setPath($path);

$fInfo = new finfo(FILEINFO_MIME);
echo
"MIME类型: ", $fInfo->file($wrapper->getStreamPath(), FILEINFO_MIME_TYPE, $wrapper->getContext()), "\n";
?>
tim at savaslabs dot com
9年前
只是想指出(因为我遇到了这个问题!)`finfo_file` 的当前实现存在已知的bug,当某些字符串出现在它正在检查的文本文件中时,会导致PHP分配大量内存。

更多信息请参见 https://bugs.php.net/bug.php?id=69224
contato at vfreitas dot com
12年前
嗯,我遇到了一个大问题,MS Office 2007 扩展名(pptx、xlsx、docx)没有默认的MIME类型,它们的MIME类型是“application/zip”,所以,为了解决这个问题,我编写了一个小函数来验证扩展名。
这个函数可以让你免受伪造扩展名攻击的风险。

<?php

$arrayZips
= array("application/zip", "application/x-zip", "application/x-zip-compressed");

$arrayExtensions = array(".pptx", ".docx", ".dotx", ".xlsx");

$file = 'path/to/file.xlsx';

$original_extension = (false === $pos = strrpos($file, '.')) ? '' : substr($file, $pos);

$finfo = new finfo(FILEINFO_MIME);

$type = $finfo->file($file);

if (
in_array($type, $arrayZips) && in_array($original_extension, $arrayExtensions))
{
return
$original_extension;
}

?>
Zane MegaLab.it
13年前
我所有的文件都返回了 application/octet-stream 或“<= 不支持”。

我发现 PHP 5.3 中内置了 magic 文件,应该使用它。系统上找到的 magic 文件可能并不总是 libmagic 期望的,因此会出错。
darko at uvcms dot com
16年前
finfo_file 在 Windows 上的另一个有趣特性。

此函数可能针对某些文件类型(例如 ppt)返回空字符串而不是 FALSE。因此,为了确保,请对输出结果进行三重检查,并在必要时提供默认类型。这是一个示例代码

$ftype = 'application/octet-stream';
$finfo = @finfo_open(FILEINFO_MIME);
if ($finfo !== FALSE) {
$fres = @finfo_file($finfo, $file);
if ( ($fres !== FALSE)
&& is_string($fres)
&& (strlen($fres)>0)) {
$ftype = $fres;
}
@finfo_close($finfo);
}
niko dot jokipalo at gmail dot com
10年前
我花了几天时间寻找和搜索具有实际纯文本描述的媒体类型数据库,例如
finfo(.png) --> "image/png" --> "PNG 图片".
在基于 Ubuntu 的操作系统中,你可以在 /usr/share/mime 中找到已翻译的数据库

http://manpages.ubuntu.com/manpages/hardy/en/man5/gnome-mime.5.html
darko at uvcms dot com
16年前
相同内容的 OO(略微改进)版本

<?php
$file
= '<somefile>';
$ftype = 'application/octet-stream';
$finfo = @new finfo(FILEINFO_MIME);
$fres = @$finfo->file($file);
if (
is_string($fres) && !empty($fres)) {
$ftype = $fres;
}
?>
jesen at protonmail dot com
25天前
使用 `finfo_file()` 时,你可能会遇到类似以下的结果,需要引起注意:`image/png; charset=binary`
powtac at gmx dot de
8 年前
小心,带有 BOM 的文件将无法正确检测!
scott at thebrain dot ca
15年前
我曾考虑使用 fileinfo 来检查文件是否为 gzip 或 bzip2。但是,压缩文件的 MIME 类型是“data”,因为压缩是一种编码而不是类型。

gzip 文件以二进制 1f8b 开头。
bzip2 文件以魔数字节 'B' 'Z' 'h' 开头。
例如:

<?php
$s
= file_get_contents("somefilepath");
if (
bin2hex(substr($s,0,2)) == '1f8b' ) {/* 可能是一个 gzip 文件 */}
if(
substr($s,0,3) == 'BZh' ){/* 可能是一个 bzip2 文件 */}
?>

我不是编码专家。我的唯一测试是使用我自己的几个编码文件。
da_kooz at hotmail dot com
11年前
这是一个包装器,可以正确识别 Microsoft Office 2007 文档。它使用、编辑和添加更多文件扩展名/mime 类型非常简单直接。

<?php
function get_mimetype($filepath) {
if(!
preg_match('/\.[^\/\\\\]+$/',$filepath)) {
return
finfo_file(finfo_open(FILEINFO_MIME_TYPE), $filepath);
}
switch(
strtolower(preg_replace('/^.*\./','',$filepath))) {
// MS Office 2007 文档开始
case 'docx':
return
'application/vnd.openxmlformats-officedocument.wordprocessingml.document';
case
'docm':
return
'application/vnd.ms-word.document.macroEnabled.12';
case
'dotx':
return
'application/vnd.openxmlformats-officedocument.wordprocessingml.template';
case
'dotm':
return
'application/vnd.ms-word.template.macroEnabled.12';
case
'xlsx':
return
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
case
'xlsm':
return
'application/vnd.ms-excel.sheet.macroEnabled.12';
case
'xltx':
return
'application/vnd.openxmlformats-officedocument.spreadsheetml.template';
case
'xltm':
return
'application/vnd.ms-excel.template.macroEnabled.12';
case
'xlsb':
return
'application/vnd.ms-excel.sheet.binary.macroEnabled.12';
case
'xlam':
return
'application/vnd.ms-excel.addin.macroEnabled.12';
case
'pptx':
return
'application/vnd.openxmlformats-officedocument.presentationml.presentation';
case
'pptm':
return
'application/vnd.ms-powerpoint.presentation.macroEnabled.12';
case
'ppsx':
return
'application/vnd.openxmlformats-officedocument.presentationml.slideshow';
case
'ppsm':
return
'application/vnd.ms-powerpoint.slideshow.macroEnabled.12';
case
'potx':
return
'application/vnd.openxmlformats-officedocument.presentationml.template';
case
'potm':
return
'application/vnd.ms-powerpoint.template.macroEnabled.12';
case
'ppam':
return
'application/vnd.ms-powerpoint.addin.macroEnabled.12';
case
'sldx':
return
'application/vnd.openxmlformats-officedocument.presentationml.slide';
case
'sldm':
return
'application/vnd.ms-powerpoint.slide.macroEnabled.12';
case
'one':
return
'application/msonenote';
case
'onetoc2':
return
'application/msonenote';
case
'onetmp':
return
'application/msonenote';
case
'onepkg':
return
'application/msonenote';
case
'thmx':
return
'application/vnd.ms-officetheme';
// MS Office 2007 文档结束

}
return
finfo_file(finfo_open(FILEINFO_MIME_TYPE), $filepath);
}

?>
To Top