\App\SupportFileSanitizer

上传文件净化与图片多规格(用户上传安全体系)。

职责:对上传文件做「内容级」安全处理——不信任扩展名,只信实际内容:

  • 魔数校验(verifyMime):finfo 读实际内容类型与扩展名白名单比对,防伪造扩展/多态载荷;
  • 图片净化(sanitizeImage):GD 重编码生成全新像素数据——EXIF/嵌入载荷随重编码剥离, 并按配置等比缩放压缩(FILE 分组 file.image_*);GIF 动图重编码丢帧,仅魔数校验;
  • 缩略图(thumbnail):按 file.thumb_* 生成缩略图变体,列表/网格展示用,详情仍取原图。 全部参数经 FILE 分组配置(站点配置页可改),开关默认安全开启。

┌────────────────── 分区导航(按此顺序阅读)──────────────────┐ 分区 1 · 安全白名单常量 REENCODE_EXTENSIONS / EXT_MIME 分区 2 · 构造注入 __construct 分区 3 · 魔数校验 isImage / verifyMime 分区 4 · 净化与缩略图 sanitizeImage / thumbnail └────────────────────────────────────────────────────────────┘

Summary

Methods
Properties
Constants
__construct()
isImage()
verifyMime()
sanitizeImage()
thumbnail()
No public properties found
REENCODE_EXTENSIONS
EXT_MIME
No protected methods found
No protected properties found
N/A
pixelGuard()
$config
N/A

Constants

REENCODE_EXTENSIONS

REENCODE_EXTENSIONS = ['jpg', 'jpeg', 'png', 'webp', 'bmp']

可 GD 重编码的图片扩展(gif 动图丢帧不重编码;svg 不在上传白名单内)

EXT_MIME

EXT_MIME = ['jpg' => ['image/jpeg'], 'jpeg' => ['image/jpeg'], 'png' => ['image/png'], 'gif' => ['image/gif'], 'webp' => ['image/webp'], 'bmp' => ['image/bmp', 'image/x-ms-bmp'], 'pdf' => ['application/pdf'], 'txt' => ['text/plain'], 'csv' => ['text/plain', 'text/csv', 'application/csv'], 'json' => ['application/json', 'text/plain'], 'log' => ['text/plain'], 'ini' => ['text/plain'], 'yaml' => ['text/plain'], 'yml' => ['text/plain'], 'conf' => ['text/plain'], 'zip' => ['application/zip', 'application/x-zip-compressed'], 'rar' => ['application/vnd.rar', 'application/x-rar-compressed', 'application/octet-stream'], '7z' => ['application/x-7z-compressed', 'application/octet-stream'], 'tar' => ['application/x-tar', 'application/octet-stream'], 'gz' => ['application/gzip', 'application/x-gzip', 'application/octet-stream'], 'doc' => ['application/msword'], 'docx' => ['application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/zip'], 'ppt' => ['application/vnd.ms-powerpoint'], 'pptx' => ['application/vnd.openxmlformats-officedocument.presentationml.presentation', 'application/zip'], 'xls' => ['application/vnd.ms-excel'], 'xlsx' => ['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/zip'], 'mp4' => ['video/mp4'], 'webm' => ['video/webm'], 'mov' => ['video/quicktime'], 'avi' => ['video/x-msvideo', 'video/avi'], 'wmv' => ['video/x-ms-wmv', 'application/octet-stream'], 'asf' => ['application/octet-stream', 'video/x-ms-asf'], 'flv' => ['video/x-flv', 'application/octet-stream'], 'rm' => ['application/octet-stream', 'application/vnd.rn-realmedia'], 'rmvb' => ['application/octet-stream'], 'mp3' => ['audio/mpeg', 'audio/mp3'], 'wav' => ['audio/wav', 'audio/x-wav', 'audio/wave'], 'epub' => ['application/epub+zip', 'application/zip'], 'mobi' => ['application/x-mobipocket-ebook', 'application/octet-stream'], 'ttf' => ['font/ttf', 'application/x-font-ttf', 'application/octet-stream'], 'otf' => ['font/otf', 'application/octet-stream'], 'woff' => ['font/woff', 'application/octet-stream'], 'woff2' => ['font/woff2', 'application/octet-stream']] : array<string,string[]>

扩展名 → 允许的实际 MIME(finfo 可靠域严格;视频/音频/字体 finfo 常回 octet-stream 放宽; OOXML 三件套与 epub 是 zip 容器,额外接受 application/zip)。

白名单理由:扩展名是用户可控的,攻击者可把脚本/载荷改名成 .jpg 上传; 用 finfo 读实际内容类型并与「该扩展名允许的真实类型」白名单比对, 才能拦截伪造扩展与多态载荷(一个文件既是合法图片又是可执行脚本)。

Properties

$config

$config : \App\Services\Admin\ConfigService

Type

ConfigService

Methods

__construct()

__construct(\App\Services\Admin\ConfigService  $config) : mixed

Parameters

\App\Services\Admin\ConfigService $config

Returns

mixed —

isImage()

isImage(string  $realPath) : bool

实际内容是否为图片(getimagesize 识别,比扩展名可信)

Parameters

string $realPath

Returns

bool —

verifyMime()

verifyMime(string  $realPath, string  $ext) : void

魔数校验:finfo 实际 MIME 必须命中扩展名允许集(防伪造扩展/多态载荷)。

Parameters

string $realPath
string $ext

Throws

\InvalidArgumentException

实际内容与扩展名不符

sanitizeImage()

sanitizeImage(string  $disk, string  $path) : array

图片净化:GD 重编码 + 超限等比缩放。

重编码生成全新像素数据(EXIF/嵌入载荷剥离);GIF 动图只读尺寸不重编码。

Parameters

string $disk
string $path

Returns

array —

thumbnail()

thumbnail(string  $disk, string  $path, int  $origWidth, int  $origHeight) : ?array

缩略图生成(列表/网格展示用;原图 ≤ 缩略图上限时不生成,前端直接取原图)。

Parameters

string $disk
string $path
int $origWidth
int $origHeight

Returns

?array —

pixelGuard()

pixelGuard(int  $width, int  $height) : bool

解码前像素数守卫:GD 全尺寸解码内存峰值 ∝ 像素数(RGBA 每像素 4 字节), 宽×高超过 file.image_max_pixels(默认 2000 万像素 ≈ 80MB 解码峰值)拒绝解码, 防超大分辨率图 OOM。0/负 = 不限制。

Parameters

int $width
int $height

Returns

bool —