根本原因是nginx默认解码uri(如%e6%b5%8b%e8%af%95.pdf→“测试.pdf”),而后端(如tomcat)若未配置uriencoding="utf-8",会用iso-8859-1二次解码导致乱码或404;解决需后端设server.tomcat.uri-encoding=utf-8,并在nginx中禁用自动解码(1.19.1+用proxy_decode_uri off,旧版用rewrite+break透传原始编码)。

在 Nginx 中使用 proxy_pass 代理后端服务(如 Tomcat、Spring Boot 等)时,若请求 URL 中包含中文文件名(例如 /download/测试.pdf),常出现 404 或乱码问题。根本原因在于:Nginx 默认对 URI 进行解码(decode),而部分后端服务(尤其 Java 生态)期望接收的是原始编码的路径(即未解码的 UTF-8 百分号编码形式),导致路径不匹配或字符解析错误。
确保后端正确处理编码(前提)
代理能否成功,首先取决于后端是否能识别并正确解码请求路径:
- Spring Boot(Tomcat)默认使用 ISO-8859-1 解码 URI,遇到中文会乱码;需在
application.properties中添加:server.tomcat.uri-encoding=UTF-8 - 若用 Undertow,需配置
undertow.url-charset=utf-8 - Java Web 应用中,也可在 Filter 或 Controller 中手动对
request.getRequestURI()做 UTF-8 重新解码(不推荐,治标不治本)
禁用 Nginx 的自动 URI 解码(关键步骤)
Nginx 在将请求转发给后端前,默认会对 URI 路径进行一次 decode(RFC 3986 兼容行为),这会把 %E6%B5%8B%E8%AF%95.pdf 变成原始中文字符,而后端再解码就出错。解决方法是让 Nginx 保持原始编码透传:
安全更新和维护 CLI Proxy API(CPA)部署与配置。用于 CPA 镜像升级、配置变更、认证目录兼容修复、上线验证与回滚。适用于用户提到“CPA 更新/升级/配置改了/容器重建/回滚”等场景。
- 在
location块中,使用proxy_pass时不要带结尾斜杠,且避免重写 URI(即不用rewrite+break) - 更可靠的方式:启用
proxy_http_version 1.1并配合proxy_set_header,但真正起作用的是——升级到 Nginx 1.19.1+ 并启用proxy_decode_uri off - 对于较老版本(如 1.18 及以前),无法关闭 decode,此时应改用
rewrite+proxy_pass绕过自动解码:
注意:该方式需谨慎,仅适用于简单路径场景location /download/ { rewrite ^/download/(.*)$ /download/$1 break; proxy_pass http://backend; }此写法利用
break阻止 Nginx 对匹配后的 URI 再次 decode,使原始编码路径(如%E6%B5%8B%E8%AF%95.pdf)原样发往后端。
验证与调试建议
排查时可从三方面入手:
- 用
curl -v "http://nginx/download/%E6%B5%8B%E8%AF%95.pdf"直接访问 Nginx,观察响应头和状态码 - 在后端加日志,打印
request.getRequestURL()和request.getQueryString(),确认收到的路径是否为百分号编码格式 - 开启 Nginx
error_log debug;(需编译含 debug 日志支持),查看[debug] ... http proxy uri:行,确认转发前的 URI 形式
补充:静态文件服务无需 proxy_pass 时的处理
如果只是 Nginx 自己 serve 中文文件(非代理),需额外设置:
-
charset utf-8;—— 控制响应头中的 charset -
underscores_in_headers on;(如有自定义 header) - 确保文件系统本身支持 UTF-8 文件名(Linux 一般默认支持,Windows 下需注意 NTFS 编码)










