必须先标准化文件名再校验后缀——提取纯文件名、去除空格、转小写、确保点号存在且非开头,最后用白名单集合比对真实后缀。

直接用 String.endsWith() 判断文件后缀是否在白名单中,**不安全也不可靠**——它无法处理大小写差异、多余空格、路径干扰和点号缺失等问题。必须先标准化文件名,再比对后缀。
提取真实文件名,剥离路径和空格
用户上传的文件名可能带完整路径(如 "C:\Users\a\photo.JPG")或首尾空格,需先清理:
- 用
FilenameUtils.getName()(Apache Commons IO)或new File(path).getName()提取纯文件名 - 调用
trim()去除前后空白字符 - 避免直接对原始
fileName调用endsWith()
统一转为小写,消除大小写敏感问题
endsWith() 区分大小写,而常见后缀如 "JPG"、"jpg"、"Jpg" 都应通过。建议将文件名和白名单后缀全部转为小写后再比对:
- 使用
fileName.toLowerCase().endsWith(".pdf") - 白名单也统一存为小写字符串(如
Set.of(".pdf", ".png", ".jpg"))
检查后缀前必须有英文点号,防止误匹配
"report.pdf".endsWith(".pdf") 正确,但 "my.pdf.backup".endsWith(".pdf") 也会返回 true,这不符合“以 .pdf 结尾”的本意。更稳妥的方式是:
- 用
String.lastIndexOf('.') > 0确保点号存在且不在开头 - 结合
String.substring()提取最后一段后缀,再查白名单 - 或改用正则:
fileName.toLowerCase().matches(".*\.((pdf|png|jpg|jpeg|txt))$")
推荐做法:用白名单集合 + 标准化后缀提取
综合以上,安全验证逻辑如下:
String cleanName = FilenameUtils.getName(fileName).trim();
int lastDot = cleanName.lastIndexOf('.');
if (lastDot whitelist = Set.of(".pdf", ".png", ".jpg", ".jpeg", ".txt");
return whitelist.contains(ext);
若不能引入 Commons IO,可用 cleanName.substring(cleanName.lastIndexOf(File.separatorChar) + 1) 替代 FilenameUtils.getName()。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











