Spring Boot 文件校验需服务端多层防御:先拦空文件和超大文件,再防伪装文件;大小校验用 getSize() 结合配置与代码双重控制;类型校验须组合扩展名白名单、MIME 辅助判断及文件头魔数校验;推荐自定义注解统一管理;大文件需流式或分片上传并逐片魔数校验。

在 Spring Boot 中校验文件大小和类型,不能只依赖前端或文件名后缀,必须在服务端做多层防御:既要拦住明显违规的请求(如空文件、超大文件),也要防止伪装文件(比如把 HTML 改成 .jpg)混入系统。
校验文件大小
Spring Boot 通过 MultipartFile 的 getSize() 方法获取字节数,单位是 byte。建议结合配置项与代码双重控制:
- 在
application.yml中设置全局上传上限(防 OOM):spring.servlet.multipart.max-file-size: 10MBspring.servlet.multipart.max-request-size: 10MB - 业务代码中再做一次精准判断,便于返回定制化提示:
if (file.getSize() > 5 * 1024 * 1024) { throw new IllegalArgumentException("单个文件不能超过 5MB"); } - 注意:
getSize()是内存中已读取的长度,不触发磁盘 IO,性能开销极小
校验文件类型
仅靠 getOriginalFilename() 取后缀或 getContentType() 判断 MIME 类型都不可靠——前者可伪造,后者由浏览器提供、极易被绕过。推荐组合使用以下三种方式:
-
扩展名白名单校验:提取后缀(用
filename.substring(filename.lastIndexOf(".") + 1)),比对预设列表(如["pdf", "xlsx", "png"]),拒绝多点、路径符号(..、/)等异常格式 -
MIME 类型二次校验:调用
file.getContentType(),但只作为辅助参考;例如"image/png"对应.png,但若传test.png却报"text/html",就该警惕 -
文件头(Magic Number)校验:读取文件前几个字节(如 PNG 是
89 50 4E 47),与真实文件类型比对。可用 Apache Tika 或手写工具类解析二进制流,这是防伪装最有效的手段
用自定义注解统一管理
把大小、扩展名、MIME 类型校验封装成一个注解,复用性高且 Controller 更干净:
- 定义
@ValidFile(maxSize = 10485760, extensions = {"pdf", "docx"}, mimeTypes = {"application/pdf"}) - 实现
ConstraintValidator<ValidFile, MultipartFile>,在isValid()中依次执行空值、大小、后缀、MIME、魔数校验 - Controller 方法参数直接标注:
@RequestParam @ValidFile MultipartFile file,失败时自动抛出MethodArgumentNotValidException,由全局异常处理器统一响应
特别注意大文件场景
如果支持上传几百 MB 甚至 GB 级文件(如 CAD、视频),需切换策略:
- 禁用默认的内存缓冲(避免 OOM),改用流式读取或分片上传
- 分片上传时,每片都做魔数校验(如首片含完整文件头),而非等全部接收完才校验
- 用 Redis 锁保障分片合并顺序,SHA-256 校验整体一致性,防止中间篡改


















