探究 WordPress `get_allowed_mime_types()` 函数的源码:如何通过过滤器自定义允许上传的文件类型。

嘿,各位代码爱好者,今天咱们聊聊WordPress里一个挺有意思的小家伙:get_allowed_mime_types()。这玩意儿,说白了,就是管着你的网站能上传啥文件,不能上传啥文件。但是呢,WordPress天生就留了个后门,让你能用过滤器(Filters)来“调戏”它,自定义允许上传的文件类型。准备好了吗?咱们这就开始一场“文件类型大冒险”!

一、get_allowed_mime_types() 是个啥?

首先,咱们得搞清楚get_allowed_mime_types() 是干嘛的。简单来说,它就是一个函数,藏在WordPress的核心里,负责返回一个数组,这个数组里面列举了所有WordPress默认允许上传的文件类型。这些文件类型,用的是MIME类型来表示,比如image/jpeg代表JPEG图片,application/pdf代表PDF文档。

你可以在WordPress的wp-includes/functions.php 文件里找到它的身影。虽然可能因为版本更新,具体行数会变,但你搜一下这个函数名,肯定能找到。

二、源码“扒皮”:看看它长啥样

咱们来简单看看这个函数的“真容”。

function get_allowed_mime_types( $user = null ) {
    $mimes = array(
        'jpg|jpeg|jpe' => 'image/jpeg',
        'gif'          => 'image/gif',
        'png'          => 'image/png',
        'bmp'          => 'image/bmp',
        'tiff|tif'     => 'image/tiff',
        'ico'          => 'image/x-icon',
        'asf|asx|wax|wmv|wmx' => 'video/asf',
        'avi'          => 'video/avi',
        'divx'         => 'video/divx',
        'mov|qt'       => 'video/quicktime',
        'mpeg|mpg|mpe' => 'video/mpeg',
        'mp4|m4v'      => 'video/mp4',
        'ogv'          => 'video/ogg',
        'webm'         => 'video/webm',
        'mkv'          => 'video/x-matroska',
        '3gp|3gpp'     => 'video/3gpp', // Can cause issues with IIS if the server does not have the proper MIME type set.
        '3g2|3gp2'     => 'video/3gpp2', // Can cause issues with IIS if the server does not have the proper MIME type set.
        'txt|asc|c|cc|h' => 'text/plain',
        'csv'          => 'text/csv',
        'rtx'          => 'text/richtext',
        'css'          => 'text/css',
        'htm|html'     => 'text/html',
        'vtt'          => 'text/vtt',
        'dfxp'         => 'application/ttaf+xml',
        'ics'          => 'text/calendar',
        'rtf'          => 'application/rtf',
        'vcf'          => 'text/vcard',
        'odt'          => 'application/vnd.oasis.opendocument.text',
        'ods'          => 'application/vnd.oasis.opendocument.spreadsheet',
        'odp'          => 'application/vnd.oasis.opendocument.presentation',
        'odg'          => 'application/vnd.oasis.opendocument.graphics',
        'odc'          => 'application/vnd.oasis.opendocument.chart',
        'odb'          => 'application/vnd.oasis.opendocument.database',
        'odf'          => 'application/vnd.oasis.opendocument.formula',
        'wpd'          => 'application/vnd.wordperfect',
        'psd'          => 'image/vnd.adobe.photoshop',
        'svg'          => 'image/svg+xml',
        'svgz'         => 'image/svg+xml',
        'eot'          => 'application/vnd.ms-fontobject',
        'ttf'          => 'font/ttf',
        'ttc'          => 'font/collection',
        'woff'         => 'font/woff',
        'woff2'        => 'font/woff2',
        'pdf'          => 'application/pdf',
        'doc'          => 'application/msword',
        'pot|pps|ppt'  => 'application/vnd.ms-powerpoint',
        'wri'          => 'application/mswrite',
        'xla|xls|xlt'  => 'application/vnd.ms-excel',
        'mdb'          => 'application/vnd.ms-access',
        'mpp'          => 'application/vnd.ms-project',
        'docx'         => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
        'docm'         => 'application/vnd.ms-word.document.macroEnabled.12',
        'dotx'         => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
        'dotm'         => 'application/vnd.ms-word.template.macroEnabled.12',
        'xlsx'         => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
        'xlsm'         => 'application/vnd.ms-excel.sheet.macroEnabled.12',
        'xltx'         => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
        'xltm'         => 'application/vnd.ms-excel.template.macroEnabled.12',
        'pptx'         => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
        'ppsm'         => 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12',
        'ppsx'         => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
        'pptm'         => 'application/vnd.ms-powerpoint.presentation.macroEnabled.12',
        'potx'         => 'application/vnd.openxmlformats-officedocument.presentationml.template',
        'potm'         => 'application/vnd.ms-powerpoint.template.macroEnabled.12',
        'mdb'          => 'application/vnd.ms-access',
        'wma'          => 'audio/x-ms-wma',
        'mp3|m4a|m4b'  => 'audio/mpeg',
        'mka'          => 'audio/x-matroska',
        'ogg|oga'      => 'audio/ogg',
        'wav'          => 'audio/wav',
        'mid|midi'     => 'audio/midi',
        'zip'          => 'application/zip',
        'rar'          => 'application/x-rar-compressed',
        'gz|gzip'      => 'application/x-gzip',
        'tar'          => 'application/x-tar',
        '7z'           => 'application/x-7z-compressed',
        'exe'          => 'application/x-msdownload',
    );

    /**
     * Filters the list of allowed mime types and file extensions.
     *
     * @since 2.0.0
     *
     * @param string[] $mimes Array of mime types keyed by the file extension regex corresponding to those types.
     * @param int|WP_User|null $user Optional. User ID, WP_User object, or null to default to current user.
     */
    return apply_filters( 'upload_mimes', $mimes, $user );
}

瞅见没?函数的主体就是一个大大的数组 $mimes,里面存着文件扩展名和对应的MIME类型的“情侣配对”。 比如 'jpg|jpeg|jpe' => 'image/jpeg',意思就是说,后缀名是jpg、jpeg或者jpe的文件,都属于image/jpeg这种类型。

最关键的是,函数最后用了一个apply_filters( 'upload_mimes', $mimes, $user );。 这句话的意思是:

  1. ‘upload_mimes’: 这是一个过滤器(Filter)的名字。
  2. $mimes: 这是要被过滤的数据,也就是我们前面那个包含了文件类型信息的数组。
  3. $user: 这个是可选参数,表示当前用户的信息。

apply_filters() 的作用就是,让开发者有机会通过挂载到 'upload_mimes' 这个过滤器上的函数,来修改 $mimes 数组。 换句话说,你可以增删改 $mimes 数组里的内容,从而改变WordPress允许上传的文件类型。

三、过滤器大法:自定义文件类型

好了,重点来了! 咱们要用过滤器来“搞事情”了。

步骤1: 找到你的“根据地”

首先,你需要找到一个地方来写你的代码。通常,我们会把自定义代码放在主题的 functions.php 文件里,或者创建一个自定义的插件。 强烈建议你创建一个自定义插件,这样即使你更换主题,你的自定义设置也不会丢失。

步骤2: 编写过滤器函数

接下来,我们需要编写一个函数,这个函数将会挂载到 'upload_mimes' 过滤器上。 这个函数接收一个参数(就是 $mimes 数组),然后你可以对这个数组进行修改,最后返回修改后的数组。

举个例子,假设你想允许上传 .svg 文件,可以这样做:

add_filter( 'upload_mimes', 'my_custom_mime_types' );

function my_custom_mime_types( $mimes ) {
  $mimes['svg'] = 'image/svg+xml';
  return $mimes;
}

这段代码的意思是:

  • add_filter( 'upload_mimes', 'my_custom_mime_types' );: 把 my_custom_mime_types 函数挂载到 'upload_mimes' 过滤器上。
  • function my_custom_mime_types( $mimes ) { ... }: 定义了 my_custom_mime_types 函数,它接收 $mimes 数组作为参数。
  • $mimes['svg'] = 'image/svg+xml';: 在 $mimes 数组中添加了一个新的键值对,表示允许上传 .svg 文件,并且它的MIME类型是 image/svg+xml
  • return $mimes;: 返回修改后的 $mimes 数组。

步骤3: 上传试试看!

把这段代码放到你的 functions.php 文件里,或者你的自定义插件里,然后上传一个 .svg 文件试试看。 如果一切顺利,你应该可以成功上传 .svg 文件了!

四、更高级的玩法:删除、修改、多扩展名

除了添加新的文件类型,你还可以删除、修改现有的文件类型,或者为同一个MIME类型添加多个扩展名。

1. 删除文件类型

如果你想禁止上传某种文件类型,可以把它从 $mimes 数组里删除。 比如,你想禁止上传 .exe 文件,可以这样做:

add_filter( 'upload_mimes', 'my_custom_mime_types' );

function my_custom_mime_types( $mimes ) {
  unset( $mimes['exe'] );
  return $mimes;
}

2. 修改文件类型

如果你想修改某个文件类型的MIME类型,可以直接修改 $mimes 数组里对应的值。 比如,你想把 .jpg 文件的MIME类型修改为 image/jpeg-custom,可以这样做:

add_filter( 'upload_mimes', 'my_custom_mime_types' );

function my_custom_mime_types( $mimes ) {
  $mimes['jpg|jpeg|jpe'] = 'image/jpeg-custom';
  return $mimes;
}

3. 添加多个扩展名

如果你想为同一个MIME类型添加多个扩展名,只需要在键名中使用 | 分隔符即可。 比如,你想让 .svg.svgz 都属于 image/svg+xml 类型,可以这样做:

add_filter( 'upload_mimes', 'my_custom_mime_types' );

function my_custom_mime_types( $mimes ) {
  $mimes['svg|svgz'] = 'image/svg+xml';
  return $mimes;
}

五、注意事项:安全第一!

虽然自定义文件类型很方便,但是一定要注意安全! 允许上传一些不安全的文件类型,可能会给你的网站带来安全风险。

  • 谨慎选择文件类型: 只允许上传你真正需要的文件类型。
  • 验证文件内容: 仅仅通过文件扩展名来判断文件类型是不够的,应该验证文件的实际内容,确保它是你期望的文件类型。 你可以使用 wp_check_filetype() 函数来检查文件的MIME类型。
  • 防止文件执行: 确保上传的文件不会被执行。 比如,不要允许上传 .php 文件,或者把上传目录设置为禁止执行脚本。

六、实战演练:自定义文件类型插件

咱们来写一个简单的插件,实现自定义文件类型的功能。

1. 创建插件文件

创建一个名为 custom-mime-types.php 的文件,放在 wp-content/plugins/ 目录下。

2. 编写插件代码

custom-mime-types.php 文件里,添加以下代码:

<?php
/**
 * Plugin Name: Custom MIME Types
 * Description: Allows you to add custom MIME types to WordPress.
 * Version: 1.0.0
 * Author: Your Name
 */

add_filter( 'upload_mimes', 'custom_mime_types' );

function custom_mime_types( $mimes ) {
    $mimes['svg'] = 'image/svg+xml';  // 允许上传 SVG 文件
    $mimes['webp'] = 'image/webp'; // 允许上传 WebP 文件
    unset( $mimes['exe'] ); // 禁止上传 EXE 文件
    return $mimes;
}

3. 激活插件

登录你的WordPress后台,找到“插件”菜单,激活“Custom MIME Types”插件。

搞定! 现在你就可以上传 .svg.webp 文件了,并且不能上传 .exe 文件。

七、常见问题与解答

  • Q: 为什么我的代码不起作用?

    • A: 确保你的代码放在了正确的地方(functions.php 或者自定义插件)。
    • A: 检查你的代码是否有语法错误。
    • A: 确保你的插件已经激活。
    • A: 检查你的服务器是否支持你添加的文件类型。
  • Q: 如何获取文件的MIME类型?

    • A: 可以使用 wp_check_filetype() 函数。
  • Q: 我可以允许上传 .php 文件吗?

    • A: 强烈不建议! 允许上传 .php 文件会给你的网站带来严重的安全风险。

八、总结

通过 get_allowed_mime_types() 函数和 'upload_mimes' 过滤器,我们可以轻松地自定义WordPress允许上传的文件类型。 但是,一定要注意安全,谨慎选择文件类型,并采取必要的安全措施,保护你的网站免受攻击。

希望今天的“文件类型大冒险”能让你有所收获! 如果你还有什么问题,欢迎随时提问。 咱们下次再见!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注