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

各位观众老爷,晚上好!我是你们今晚的 WordPress 源码解读小助手。今天咱们的主题是:如何优雅地玩转 WordPress 的 get_allowed_mime_types() 函数,让它听你的话,允许你上传任何你想上传的文件类型!

准备好了吗?咱们这就开始,争取让大家听完之后,也能成为 WordPress 文件上传权限管理的“老司机”!

一、get_allowed_mime_types():文件上传的守门员

首先,我们要认识一下今天的主角 get_allowed_mime_types()。这个函数的作用很简单粗暴,就是返回一个数组,里面包含了 WordPress 允许上传的所有 MIME 类型。MIME 类型,你可以理解为文件的“身份证”,告诉浏览器这是什么类型的文件。

这个函数藏身于 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 also be audio
        '3g2|3gp2'     => 'video/3gpp2', // Can also be audio
        'txt|asc|c|cc|h|srt' => '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',
        'mp3|m4a|m4b'  => 'audio/mpeg',
        'mpga'         => 'audio/mpeg',
        'ogg|oga|spx'  => 'audio/ogg',
        'wav'          => 'audio/wav',
        'mid|midi'     => 'audio/midi',
        'wma'          => 'audio/x-ms-wma',
        'mka'          => 'audio/x-matroska',
        'rtf'          => 'application/rtf',
        'js'           => 'application/javascript',
        'pdf'          => 'application/pdf',
        'doc|docx'     => 'application/msword',
        'pot|pps|ppt'  => 'application/vnd.ms-powerpoint',
        'wri'          => 'application/x-mswrite',
        'xla|xls|xlt'  => 'application/vnd.ms-excel',
        'xlam|xlsx|xltx|xlsm|xlsb|xltm' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
        'mdb'          => 'application/msaccess',
        'psd'          => 'image/vnd.adobe.photoshop',
        'rar'          => 'application/rar',
        'zip|gz|tar|7z' => 'application/zip',
        'exe'          => 'application/x-msdownload',
        'key|numbers|pages' => 'application/vnd.apple.keynote',
    );

    /**
     * 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 use the current user.
     */
    return apply_filters( 'upload_mimes', $mimes, $user );
}

可以看到,这个函数的核心就是一个 $mimes 数组,里面定义了各种文件扩展名和对应的 MIME 类型。 例如,'jpg|jpeg|jpe' => 'image/jpeg' 就表示 .jpg.jpeg.jpe 文件都属于 image/jpeg 类型的图片。

二、upload_mimes 过滤器:掌控上传的钥匙

仔细观察上面的代码,你会发现最后一行:return apply_filters( 'upload_mimes', $mimes, $user );。 这个 apply_filters 函数就是关键所在! 它允许我们通过 upload_mimes 过滤器来修改 $mimes 数组,从而改变 WordPress 允许上传的文件类型。

你可以把 apply_filters 想象成一个“拦截器”,在 get_allowed_mime_types() 函数返回 $mimes 数组之前,它会检查是否有哪个函数注册了 upload_mimes 过滤器。 如果有,它就会把 $mimes 数组交给这些函数处理,处理完之后再返回。

三、实战演练:添加自定义文件类型

现在,咱们来演示如何使用 upload_mimes 过滤器添加自定义文件类型。 假设我们想允许上传 .svg 文件。

  1. 找到 functions.php 首先,找到你主题的 functions.php 文件。 如果没有,就创建一个。 functions.php 文件是主题的“大脑”,你可以在里面添加自定义的 PHP 代码。

  2. 添加过滤器:functions.php 文件中添加以下代码:

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' );:这行代码告诉 WordPress,我们要使用 my_custom_mime_types 函数来处理 upload_mimes 过滤器。
  • function my_custom_mime_types( $mimes ) { ... }:这就是我们自定义的函数。 它接收 $mimes 数组作为参数,然后向数组中添加了 'svg' => 'image/svg+xml' 这一项,表示允许上传 .svg 文件。 最后,它返回修改后的 $mimes 数组。
  1. 保存并测试: 保存 functions.php 文件,然后尝试在 WordPress 后台上传一个 .svg 文件。 如果一切顺利,你应该能够成功上传!

四、更高级的玩法:删除或修改现有文件类型

除了添加新的文件类型,我们还可以删除或修改现有的文件类型。

  • 删除文件类型:
add_filter( 'upload_mimes', 'my_custom_mime_types' );

function my_custom_mime_types( $mimes ) {
  unset( $mimes['exe'] ); // 禁止上传 .exe 文件
  return $mimes;
}

这段代码使用 unset() 函数删除了 $mimes 数组中的 'exe' 这一项,从而禁止上传 .exe 文件。

  • 修改文件类型:
add_filter( 'upload_mimes', 'my_custom_mime_types' );

function my_custom_mime_types( $mimes ) {
  $mimes['jpg|jpeg|jpe'] = 'image/jpeg'; // 保持原样,但可以修改成其他类型
  return $mimes;
}

这段代码修改了 'jpg|jpeg|jpe' 对应的 MIME 类型。 虽然这里保持了原样,但你可以将其修改成其他类型,例如 'image/webp'。 不过要注意,修改现有文件类型可能会导致一些问题,需要谨慎操作。

五、MIME 类型对照表:方便查询

为了方便大家查找各种文件类型对应的 MIME 类型,我整理了一个简单的对照表:

文件扩展名 MIME 类型 说明
.jpg image/jpeg JPEG 图像
.png image/png PNG 图像
.gif image/gif GIF 图像
.svg image/svg+xml SVG 图像
.pdf application/pdf PDF 文档
.zip application/zip ZIP 压缩文件
.mp3 audio/mpeg MP3 音频
.mp4 video/mp4 MP4 视频
.txt text/plain 纯文本文件
.csv text/csv CSV 文件
.doc application/msword Microsoft Word 文档 (.doc)
.docx application/vnd.openxmlformats-officedocument.wordprocessingml.document Microsoft Word 文档 (.docx)
.xls application/vnd.ms-excel Microsoft Excel 文档 (.xls)
.xlsx application/vnd.openxmlformats-officedocument.spreadsheetml.sheet Microsoft Excel 文档 (.xlsx)

这个表格只是冰山一角,更多的 MIME 类型可以在网上找到。 例如,MDN Web Docs 就提供了非常详细的 MIME 类型列表:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types

六、安全提醒:别玩火自焚

虽然我们可以通过 upload_mimes 过滤器来允许上传任何文件类型,但这并不意味着我们可以为所欲为。 上传恶意文件可能会导致安全问题,例如:

  • 代码注入: 如果允许上传 PHP 文件,攻击者就可以上传包含恶意代码的 PHP 文件,从而控制你的网站。
  • 跨站脚本攻击(XSS): 如果允许上传 HTML 或 SVG 文件,攻击者就可以上传包含恶意 JavaScript 代码的文件,从而窃取用户的 Cookie 或执行其他恶意操作。

因此,在修改 upload_mimes 过滤器时,一定要谨慎考虑安全问题。 只允许上传你真正需要的文件类型,并对上传的文件进行安全检查。

七、总结:掌控文件上传,安全第一

今天我们一起学习了如何使用 get_allowed_mime_types() 函数和 upload_mimes 过滤器来控制 WordPress 允许上传的文件类型。 希望大家能够掌握这些技巧,让 WordPress 更加符合你的需求。

记住,能力越大,责任越大。 在享受自定义文件上传的便利的同时,也要时刻注意安全问题。 不要让你的网站成为攻击者的乐园!

好了,今天的讲座就到这里。 感谢大家的收听! 如果有什么问题,欢迎在评论区留言,我会尽力解答。 下次再见!

发表回复

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