文件名乱码源于服务端解析multipart/form-data时对中文文件名编码处理错误:Java需手动用ISO-8859-1转UTF-8解码,PHP推荐iconv清洗,HTML须设enctype="multipart/form-data"且页面为UTF-8无BOM。

文件名乱码不是前端 HTML 本身的问题,而是服务端接收 multipart/form-data 时对文件名编码解析错误导致的。浏览器上传中文文件名时,不同内核(Chrome/Firefox/Safari)实际编码行为不一致,服务端若不做适配,item.getName() 或 $_FILES['file']['name'] 拿到的就是乱码字节流。
Java Servlet + Apache Commons FileUpload:文件名解码必须手动处理
FileUpload 默认用 ISO-8859-1 解析字段值,但中文文件名在 HTTP 请求体中实际是 UTF-8 编码的原始字节 —— 所以直接调 item.getString() 会错解。不能只靠 request.setCharacterEncoding("UTF-8"),它只影响普通表单字段,对文件名无效。
-
item.isFormField()为false时,才是文件项,此时必须用字节重解码:String fileName = new String(item.getName().getBytes("ISO-8859-1"), "UTF-8"); - 如果项目用了 Spring MVC,推荐直接用
@RequestParam MultipartFile file,Spring 已自动处理文件名编码(前提是容器配置了CharacterEncodingFilter) - 注意:这个
new String(...)方式在 Tomcat 8.5+、Jetty 9+ 上基本可用,但若后端用了 SmartUpload 或自定义解析器,可能抛UnsupportedEncodingException,得加 try-catch
PHP:iconv 是最稳妥的兼容方案
PHP 的 $_FILES 数组里 name 字段在不同 PHP 版本和 SAPI(Apache module / FPM)下表现不一。依赖 mb_convert_encoding() 可能失败,iconv() 更底层、更可控。
- 先判断是否已为 UTF-8:
$name = $_FILES['file']['name'];<br>if (mb_detect_encoding($name, 'UTF-8, GBK, BIG5') !== 'UTF-8') {<br> $name = iconv('GBK', 'UTF-8//IGNORE', $name);<br>} - 更通用写法(覆盖常见来源):
$name = iconv('UTF-8', 'UTF-8//IGNORE', $name); // 清洗 BOM 和非法序列<br>$name = iconv('GBK', 'UTF-8//IGNORE', $name);<br>$name = iconv('BIG5', 'UTF-8//IGNORE', $name); - 别漏掉
//IGNORE,否则遇到无法转换字符会报 Warning 并中断
HTML 表单本身要配合:accept-charset 不起作用,但 enctype 必须正确
accept-charset="UTF-8" 对 multipart/form-data 完全无效 —— 浏览器忽略它。真正关键的是两点:form 的 enctype 和页面本身的编码声明。
立即学习“前端免费学习笔记(深入)”;
- form 必须显式声明:
enctype="multipart/form-data",缺省或写错(如text/plain)会导致整个上传失败或字段丢失 - HTML 页面必须保存为 UTF-8 无 BOM 格式,并在
<head>中第一行放:</meta charset="UTF-8">;否则浏览器可能用 GBK 解析整个页面,连带影响文件名提交时的原始字节解释 - 不要用
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">,HTML5 已废弃该写法,且某些旧版 IE 会误判
最容易被忽略的点是:服务端代码里对文件名的处理往往夹杂在一堆 IO 操作中,没人专门去验证 item.getName() 或 $_FILES['file']['name'] 的原始字节内容。建议上传后立刻用 hexdump 或 bin2hex() 打印原始 name 字节,再比对期望的 UTF-8 编码,才能准确定位到底是前端传歪了,还是后端解歪了。



















