@PathVariable接收fileName时合法扩展名请求返回406 Not Acceptable问题
问题分析
这个问题典型得很,一看就是Web框架的**内容协商(Content Negotiation)**机制在搞事情——406 Not Acceptable本身就是说服务器没法生成符合客户端Accept头要求的响应,而这里刚好是「合法扩展名触发406,非法扩展名正常返回JSON」,根源大概率是框架自动把常见扩展名和特定媒体类型绑定了,和你要返回的JSON格式冲突了:
- 对于
item-1.exx、item-1.855这类「非标准扩展名」,框架找不到对应的默认媒体类型,就会 fallback 到你处理器默认的响应类型(比如application/json),所以能正常返回包含文件名的JSON。 - 对于
.png、.jpg、.exe这类标准扩展名,框架会自动关联对应的媒体类型(比如.png对应image/png,.exe对应application/octet-stream),如果你的处理器没有明确指定返回JSON,或者客户端的Accept头不包含这些媒体类型,就会触发406错误。
排查与解决方案
1. 先确认请求的Accept头
用curl或Postman发起请求时,检查请求头里的Accept字段:
- 如果客户端发送的是
Accept: application/json,但框架认为.png应该返回image/png,两者不匹配就会返回406。 - 示例curl命令:
curl -v http://your-domain/test/item-1.png -H "Accept: application/json"
2. 禁用框架的「扩展名驱动内容协商」
很多Web框架(比如Spring Boot、ASP.NET)默认会根据URL后缀自动推断响应媒体类型,你可以直接禁用这个功能:
- Spring Boot:在
application.properties里添加配置:spring.mvc.contentnegotiation.favor-path-extension=false # 或者更彻底一点,关闭后缀匹配 spring.mvc.pathmatch.matching-strategy=PATH_PATTERN_PARSER - JAX-RS(Jersey):移除
MediaTypeMappingFeature相关配置,或者在资源方法上明确覆盖媒体类型。
3. 强制指定处理器方法的响应类型
在你的处理器方法上,明确声明返回application/json,不管URL后缀是什么:
- Spring MVC示例:
@GetMapping(value = "/test/{fileName}", produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity<Map<String, String>> getFileName(@PathVariable String fileName) { Map<String, String> response = new HashMap<>(); response.put("fileName", fileName); return ResponseEntity.ok(response); } - 这样配置后,服务器会强制返回JSON格式,只要客户端的
Accept头包含application/json(或者客户端不指定Accept头),就不会再返回406。
4. 自定义媒体类型映射(如果需要保留扩展名功能)
如果你既要保留扩展名和媒体类型的关联,又要让这些路径能返回JSON,可以添加自定义映射:
- Spring Boot示例:在配置类里添加:
这样框架会把这些扩展名也映射到JSON类型,自然就能正常返回了。@Configuration public class WebConfig implements WebMvcConfigurer { @Override public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { configurer .favorPathExtension(true) .mediaType("png", MediaType.APPLICATION_JSON_VALUE) .mediaType("jpg", MediaType.APPLICATION_JSON_VALUE) .mediaType("exe", MediaType.APPLICATION_JSON_VALUE); } }
内容的提问来源于stack exchange,提问作者A0__oN
相关产品推荐
相关产品推荐

