vue前端downloadFile报错:Error parsing HTTP request header;java.lang.IllegalArgumentException
vue前端downloadFile报错
- 出现场景
- 具体日志
- 思路
- 解决
- 其他
出现场景
项目已经部署生产开始使用,突然有一个功能点击后,整个界面一直显示加载中不能点击其他按钮。
一直加载是表象某个loading置true没改回来(类似一个最大的div置表层,只显示loading,这也导致其他按钮点不了,“卡死”状态)。
F12检查,功能有一个特点,附件只有一个的时候会默认启动下载download功能,同时download报错爆红400,同时导致前端loading没有修改状态。
所以解决这个download爆红。
具体日志
Error parsing HTTP request header
java.lang.IllegalArgumentException: Invalid character found in the request target [/knowledge/file/download?fileName=%E5%85%B3%E4%BA%8E%E8%A7%84%E8%8C%83%E4%BC%A0%E6%9F%93%E6%80%A7%E7%96%BE%E7%97%85%E6%A3%80%E6%B5%8B%E6%A0%B7%E6%9C%AC%E9%80%81%E6%A3%80%E5%B7%A5%E4%BD%9C%E7%9A%84%E9%80%9A%E7%9F%A5%EF%BC%88%E7%A9%97%E7%96%BE%E6%8E%A7%E5%8A%9E[2018]52%E5%8F%B7%EF%BC%89.docx ]. The valid characters are defined in RFC 7230 and RFC 3986
项目已经部署,这是运维在服务器端给出的日志,F12检查只有一个方法爆红,点击进去显示response里面是400状态。
思路
1.运维给出了一个图片,叽里咕噜看不懂,直接给ai,ai反应很快给出思路。
原因分析 RFC 7230 和 RFC 3986 定义了 HTTP
请求目标中允许的有效字符。出现该错误,一般是因为请求路径或请求参数中包含了这些规范之外的字符。比如在文件名参数 fileName
的值中,可能存在特殊字符组合(从日志看编码后的文件名包含了如 %E5 等编码字符),导致不符合规范。
正好,这个方法是download?filename=xxxxx,大概就是请求时url出现问题,瞄一眼出问题文档名字,果然是有一些特殊字符。
2.首先想到先搞一个断点,但是已操作发现是“真正的400”,不是自己定义的msg、code,那就可能是什么拦截器、过滤器?先不看,这种要么前端,要么后端解决了理论上都没问题。
3.再找前端发请求处,果然,前端直接将参数给出了,如下:
export function handleDownload(fileName) { return request({ url: '/knowledge/file/download?fileName='+fileName, method: 'get', responseType: 'blob' }) }
解决
修改了前端发请求的参数,我的问题仅仅修改完前端的就ok了,各位的就自己再具体情况,具体分析一下了。
(图片来源网络,侵删)export function handleDownload(fileName) { // 对文件名进行URL编码,确保特殊字符正确传输 const encodedFileName = encodeURIComponent(fileName); return request({ url: `/knowledge/file/download?fileName=${encodedFileName}`, method: 'get', responseType: 'blob' }) }
修改说明:
- 编码处理:使用encodeURIComponent()对文件名进行编码,将特殊字符(如中文、空格、标点符号等)转换为符合 RFC 3986 规范的 URL 安全格式(例如%E5%85%B3%E4%BA%8E)。
- 避免硬拼接:使用模板字符串${encodedFileName}替代字符串拼接,提高代码可读性。
注意事项:
(图片来源网络,侵删)- 后端解码:后端接收到参数后,需要使用对应的解码方法(如 Java 的URLDecoder.decode())对参数进行解码,恢复原始文件名。
兼容性:encodeURIComponent()是 JavaScript 内置函数,所有现代浏览器均支持。
其他
请求:url: '/knowledge/file/download?fileName='+fileName如果有上述url编码问题会有一下的情况。
-
直接抛出 400 错误,不进入业务方法(不进controller,断点没用)Tomcat 等容器默认处理 :像 Tomcat 这类 Web 服务器容器,当请求中包含不符合 RFC 7230 和 RFC 3986 规范的字符时,它的 HTTP 请求解析机制会直接抛出异常。
(图片来源网络,侵删)例如本次:java.lang.IllegalArgumentException 异常 。在这种情况下,请求根本不会到达后端的业务方法,而是在容器处理请求头解析阶段就终止,直接返回 400 Bad Request 给前端。
-
进入拦截器等预处理组件
过滤器 / 拦截器处理 :若后端配置了全局过滤器(Filter)或拦截器(Interceptor ,如 Spring 框架中的 HandlerInterceptor ),且它们在请求处理链靠前的位置,请求会先进入这些组件。在这些组件中可以对请求进行合法性检查,包括检查请求参数是否符合规范。如果发现参数不符合 RFC 规范,可以直接在过滤器 / 拦截器中处理
比如返回自定义错误响应,此时也不会进入具体业务方法。
-
全局异常处理器介入 :即使请求经过一些处理进入了后端业务方法,但在方法执行过程中由于参数不符合规范导致抛出异常,若项目配置了全局异常处理器(如 Spring 中的@ControllerAdvice和@ExceptionHandler组合 ),异常会被全局异常处理器捕获处理,根据异常类型返回合适的错误响应,也可能返回 400 状态码。