Spring Boot图片上传需四重校验:扩展名、MIME类型(白名单限定image/png/jpeg/jpg)、文件头魔数(如PNG的89504E47、JPEG的FFD8FF)、可执行特征检测,且文件大小≤10MB,依赖Apache Tika并结合AOP或手动调用实现。

文件类型校验:用 MIME 类型 + 扩展名双保险
仅靠扩展名容易被伪造,建议结合 MultipartFile.getContentType() 和文件头(magic number)校验。实际开发中可先用白名单限制常见类型:
- 图片类:image/jpeg、image/png、image/gif(注意 GIF 动图也属 image/gif)
- 文档类:application/pdf、application/msword、application/vnd.openxmlformats-officedocument.wordprocessingml.document
- 避免使用通配符如
image/*,防止绕过(如上传 HTML 冒充 image/svg+xml) - 扩展名需统一小写比对(
fileName.toLowerCase().endsWith(".pdf")),并校验原始文件名是否含非法字符(如../、空字节)
文件大小限制:服务端必须校验,不能只靠前端
Spring Boot 默认单文件上限 1MB,需在 application.yml 中显式配置:
spring.servlet.multipart.max-file-size: 10MBspring.servlet.multipart.max-request-size: 10MB
业务层再做二次校验更稳妥:if (file.getSize() > 10 * 1024 * 1024) { throw new IllegalArgumentException("文件不能超过 10MB"); }
注意:getSize() 返回的是字节数,不是字符串长度,无需读取流内容即可获取。
存储路径处理:按业务隔离 + 时间分片 + 安全命名
避免所有文件存同一目录,防止 Linux 单目录文件数过多影响性能,也便于权限控制和清理:
- 路径结构示例:
/upload/avatar/2024/06/25/abc123.png(按模块、年月日分层) - 原始文件名弃用,改用 UUID + 时间戳生成唯一名(如
UUID.randomUUID().toString().replace("-", "") + "_" + System.currentTimeMillis()) - 存储前检查目标目录是否存在,自动创建:
Files.createDirectories(Paths.get(uploadDir)) - 绝对路径不要拼接用户输入,用
Paths.get(baseDir, subPath...)防止路径遍历
封装成工具类:一个方法完成三重校验与保存
把上述逻辑收拢为 FileUploadService.upload(MultipartFile file, UploadConfig config):
- config 包含允许类型列表、最大字节数、基础存储路径、业务模块标识
- 方法内依次执行:空值检查 → 类型校验 → 大小校验 → 重命名 → 构建安全路径 → 写入磁盘 → 返回访问 URL 或存储元数据
- 异常统一包装为自定义异常(如
InvalidUploadException),便于全局异常处理器拦截返回友好提示
这样调用方只需传文件和配置,不关心底层细节,真正实现“封装”——隐藏复杂性,暴露简洁接口。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











