java上传文件名安全过滤需分层拦截:先用paths.get().getfilename()提取纯文件名防路径遍历;再清理windows禁止字符、控制符并限长≤80;接着按使用场景选gbk或utf-8编码校验可转码性;最后uuid重命名+白名单校验扩展名,存储于web根目录外无执行权限目录。

Java 对上传文件名做安全过滤,核心目标是防路径遍历、防非法字符、防编码冲突、防覆盖和跨平台乱码。不是简单“替换空格”,而是分层拦截+清洗+标准化。
提取纯文件名,剥离路径
用户可能传 ../../etc/passwd 或 C: mpshell.jsp,必须只保留末尾真实文件名:
- 用
Paths.get(fileName).getFileName().toString()提取,不依赖字符串截取 - 避免直接调用
file.getName()或substring(),它们无法识别 Windows 路径分隔符或 UNC 路径 - 若结果为空(如仅传
../),应拒绝该请求
过滤危险字符与非法结构
Windows 和部分解压工具对文件名有硬性限制,需主动清理:
Java开发手册规约集合,基于阿里巴巴Java开发手册(嵩山版)。 涵盖7大维度:编程规约、异常日志、单元测试、安全规约、MySQL数据库、工程结构、设计规约。 当用户需要:(1) 编写或审查Java代码 (2) 检查命名/代码规范 (3) 处理异常和日志 (4) 编写单元测试 (5) 安全编码 (6) 数据库设...
- 删除或替换
/ : * ? " |(Windows 禁止字符) - 去除首尾空格、不可见控制字符(如
u200b、uFEFF) - 限制总长度 ≤ 80 字符(兼顾 ZIP 工具、iOS 文件 App、旧版 Android)
- 正则示例:
fileName.replaceAll("[\\/:*?"|\x00-\x1f]", "_")
统一编码并校验可转码性
中文乱码本质是写入编码与解压端解析不一致。不能假设“UTF-8 万能”:
- 若服务端用
ZipOutputStream压缩下载,且目标为 Windows 资源管理器 → 优先用 GBK 编码写入,并确保原始字符串能无损转 GBK(例如含 emoji 或生僻字时会失败) - 若仅 Java 客户端解压 → 明确使用
new ZipOutputStream(out, StandardCharsets.UTF_8) - 对变量名做预检:
"张三".getBytes(StandardCharsets.GBK).length == 4;若抛UnsupportedEncodingException,说明含 GBK 不支持字符,应替换或报错
重命名生成安全唯一文件名
防御覆盖、猜解、重复上传,同时保留原始语义(便于人工识别):
- 拼接方式建议:
UUID.randomUUID() + "_" + sanitizedBaseName + ext - 扩展名必须从原始文件严格提取(
fileName.substring(fileName.lastIndexOf("."))),不能信任客户端传的Content-Type - 白名单校验扩展名(如
.jpg .pdf .xlsx),拒绝无扩展名或双扩展名(shell.jsp.jpg) - 存储路径必须固定在 Web 根目录外,且禁用执行权限(如 Linux 下
chmod -x upload_dir)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










