composer 不安装前端上传组件,upload 校验需自行在 php 或前端实现;php 层校验依赖 upload_max_filesize 配置,且必须用 mimetypes/mimes 而非仅扩展名,否则存在安全风险。

Composer 本身不提供 Upload 组件,也不会安装任何前端上传组件。你执行 composer require 得到的永远是 PHP 包(比如 symfony/http-foundation、laravel/framework 或 mix/http-message),不是 Ant Design 的 Upload 组件。混淆这点会导致后续所有配置失效。
为什么 composer install 后找不到 Upload 校验逻辑
因为 Upload 是前端 UI 组件(React/Vue),它的“校验”发生在浏览器端或服务端接收后,和 Composer 完全无关。Composer 只负责把 PHP 依赖装进 vendor/,而文件校验规则要你自己写在 PHP 代码里,或通过前端框架配 rules、beforeUpload 等。
- Ant Design 的
Upload是 React 组件,校验靠Form.Item rules+fileList状态管理 - Symfony 用
File约束类,需手动注入UploadedFile对象并调用$validator->validate() - Laravel 用
request->validate(['file' => 'required|file|mimes:pdf,jpg']),底层走的是Illuminate\Validation\Rules\File - MixPHP 或 Yii2 的上传行为(如
mohorev/yii2-upload-behavior)才真正由 Composer 安装,但校验仍需你在模型或表单类中显式定义
Symfony 的 File 约束必须配 mimeTypes 才安全
只写 maxSize 不够,攻击者可伪造 Content-Type 绕过。必须搭配 mimeTypes 并确保 symfony/mime 已安装,否则会退化为仅检查扩展名。
- 没装
symfony/mime:mimeTypes: ['image/png']实际只查$file->getClientOriginalExtension() - 装了但没启用:需在验证器中显式使用
new UploadedFile($file)构造对象,不能直接传$_FILES原始数组 - 正确写法示例:
use Symfony\Component\Validator\Constraints as Assert;<br><br>public function configureOptions(OptionsResolver $resolver)<br>{<br> $resolver->setDefaults([<br> 'constraints' => [<br> new Assert\File([<br> 'maxSize' => '2M',<br> 'mimeTypes' => ['image/jpeg', 'image/png'],<br> 'mimeTypesMessage' => '只允许 JPG 或 PNG 图片',<br> ]),<br> ],<br> ]);<br>}
Laravel 验证器里 extensions 和 mimes 的区别
mimes 检查 MIME 类型(需读取文件头),extensions 只看后缀名。生产环境必须用 mimes,否则 evil.php.jpg 会被放行。
-
'file' => 'mimes:jpeg,png,pdf'→ 底层调用finfo_file(),可靠 -
'file' => 'extensions:jpg,png,pdf'→ 仅截取getClientOriginalName()最后一段,不可信 - 注意:Laravel 10+ 默认禁用
finfo扩展时会 fallback 到扩展名,所以部署前必须确认php -m | grep fileinfo有输出 - 额外加固:在
AppServiceProvider::boot()中加Validator::extend('safe_mime', function ($attribute, $value, $parameters) { ... });强制双检
最易被忽略的一点:所有 PHP 层校验都依赖 $_FILES 数组的原始数据,而这个数组在 PHP 接收请求时已被 upload_max_filesize 和 post_max_size 截断。如果这两个 ini 值设得太小,文件根本到不了你的验证逻辑——Composer 无法管这事,得靠部署脚本提前检查 ini_get('upload_max_filesize')。











