CodeIgniter作为一款轻量级的PHP框架,在文件上传、文件校验这类常见业务上提供了不少开箱即用的工具函数。其中get_mimes就是一个容易被忽视但非常实用的全局函数,它的职责很简单:返回一个包含各类文件扩展名与MIME类型映射关系的多维数组。很多开发者在做文件上传白名单校验时,习惯手写一个扩展名数组硬编码在业务代码里,这种做法不仅维护成本高,而且容易遗漏一些特殊格式。了解get_mimes的用法之后,你会发现框架早就替你准备好了完整且可扩展的MIME映射数据。

一、什么是MIME类型以及为什么需要get_mimes
MIME(Multipurpose Internet Mail Extensions)类型最初是为邮件系统设计的,用来标识数据的内容格式,后来被HTTP协议广泛采用。当浏览器向服务器发送一个文件时,请求头中的Content-Type字段就是MIME类型,比如图片是image/jpeg,PDF文档是application/pdf。服务器端拿到这个信息后,才能正确判断如何处理这份上传数据。
在CodeIgniter中,MIME映射数据集中存放在application/config/mimes.php配置文件里。这个文件返回一个大的关联数组,键是文件扩展名,值是该扩展名对应的MIME类型字符串,或者是包含多个MIME类型的数组。例如txt对应text/plain,而一些格式如avi可能对应多个MIME值。get_mimes函数本质上就是对这个配置文件的封装读取器,它帮你处理了加载配置、缓存数据这些细节,你只需要调用即可。
如果不用框架封装的函数,自己维护一份映射表会面临几个问题:一是MIME类型标准会随时间更新,新文件格式不断出现;二是同一个扩展名在不同操作系统或浏览器下的MIME值可能不一致;三是散落在各处的硬编码数组难以统一修改。get_mimes把这些问题收敛到单一配置源,改一处即可全局生效。
二、get_mimes函数的定义与返回结构
这个函数定义在框架的公共函数文件中,任何地方都可以直接调用,不需要先实例化某个类。它的函数签名非常简洁:
if ( ! function_exists('get_mimes'))
{
/**
* 返回MIME类型映射数组
* @return array
*/
function get_mimes()
{
global $mimes;
if (empty($mimes))
{
// 兼容不同版本的路径常量
$mimes_path = defined('ENVIRONMENT') && is_file(APPPATH.'config/'.ENVIRONMENT.'/mimes.php')
? APPPATH.'config/'.ENVIRONMENT.'/mimes.php'
: APPPATH.'config/mimes.php';
if (is_file($mimes_path))
{
$mimes = include($mimes_path);
}
else
{
$mimes = array();
}
}
return $mimes;
}
}从实现可以看出几个要点。第一,它使用了全局变量$mimes做简单缓存,同一个请求周期内多次调用只会加载一次配置文件,性能开销可以忽略。第二,它支持按环境加载不同的mimes.php,比如你在开发环境和生产环境需要不同的映射策略时,可以分别准备config/development/mimes.php和config/production/mimes.php。第三,当配置文件不存在时返回空数组而不是报错,保证了调用的健壮性。
调用后的返回结构大致如下:
$mimes = get_mimes();
/*
返回内容形如:
array(
'txt' => 'text/plain',
'htm' => array('text/html', 'text/*'),
'html' => 'text/html',
'jpg' => array('image/jpeg', 'image/pjpeg'),
'png' => 'image/png',
'zip' => array('application/x-zip', 'application/zip', 'application/x-zip-compressed'),
'pdf' => array('application/pdf', 'application/x-download'),
...
)
*/注意值的两种形态:单个字符串表示该扩展名只对应一种MIME类型,数组则表示可能对应多种。这一点在后续做校验比对时必须考虑,否则用简单的字符串相等判断会漏掉部分合法情况。
三、实际应用场景与代码示例
最常见的场景是文件上传校验。虽然CodeIgniter的文件上传类内部已经依赖这套映射数据,但当你需要自定义校验逻辑时,直接调用get_mimes会更灵活。下面是一个手动校验上传文件MIME类型的例子:
$allowed = array('jpg', 'png', 'gif', 'pdf');
// 获取上传文件扩展名
$ext = strtolower(pathinfo($_FILES['userfile']['name'], PATHINFO_EXTENSION));
$mimes = get_mimes();
if ( ! isset($mimes[$ext]) || ! in_array($ext, $allowed))
{
exit('文件类型不被允许');
}
// 通过finfo获取文件真实MIME类型
$finfo = new finfo(FILEINFO_MIME_TYPE);
$real_mime = $finfo->file($_FILES['userfile']['tmp_name']);
// 扩展名对应的合法MIME列表
$expected = $mimes[$ext];
// 统一转成数组再比对
if (is_string($expected))
{
$expected = array($expected);
}
if ( ! in_array($real_mime, $expected, true))
{
exit('文件内容与扩展名不符,疑似伪造文件');
}
echo '校验通过';这段代码体现了安全校验的核心思路:仅信任扩展名是不够的,因为攻击者完全可以把一个PHP脚本改名为jpg上传。通过finfo读取文件内容的真实MIME类型,再与get_mimes返回的标准映射比对,才能有效拦截伪造文件。比对这个环节要记得用is_string判断后转数组,这是新手最容易踩的坑。
另一个场景是在不需要完整文件上传类的轻量接口里做格式识别。比如一个只接收JSON上传的接口,可以先用get_mimes确认json扩展名的标准MIME值,再检查Content-Type请求头是否匹配,代码量比引入整个上传类少得多。此外,如果你要扩展系统支持的文件类型,只需在config/mimes.php里追加对应的键值对,get_mimes会自动读取到新配置,业务代码无需任何改动。
总结一下,get_mimes的优势在于数据集中、调用简单、支持环境级覆盖。配合finfo做双重校验,能显著提升文件上传环节的安全性。需要留意的是它返回的是静态映射,个别浏览器上报的特殊MIME值可能不在映射表内,遇到误拦截时可以在配置文件中为该扩展名追加对应值即可解决。
CodeIgniterget_mimesMIME类型修改时间:2026-09-16 14:42:53