Spring Boot解压GZIP请求后无法触发JSON接收接口怎么办?
解决方案:Angular/Spring Boot GZIP压缩请求适配问题
你遇到的Content type '' not supported错误,核心原因有两个:一是Angular端发送Blob时未指定正确的Content-Type,二是Spring Boot的请求包装器没有保留原请求的Content-Type头,导致Spring无法识别请求格式。以下是具体修复步骤:
1. 修正Angular端请求配置
创建Blob时必须显式指定application/json类型,同时确保Content-Encoding和Content-Type头都正确设置:
const jsonBody = JSON.stringify(request.body); const compressedBody = pako.gzip(jsonBody); // 创建Blob时指定Content-Type为application/json const blobCompressedBody = new Blob([compressedBody], { type: 'application/json' }); const newRequest = request.clone({ headers: request.headers .append('Content-Encoding', 'gzip') .set('Content-Type', 'application/json'), body: blobCompressedBody });
2. 完善Spring Boot的请求包装器
你的GzippedInputStreamWrapper需要重写getContentType()和相关头信息方法,确保原请求的内容类型不丢失:
public class GzippedInputStreamWrapper extends HttpServletRequestWrapper { private final InputStream inputStream; public GzippedInputStreamWrapper(HttpServletRequest request) throws IOException { super(request); try { this.inputStream = new GZIPInputStream(request.getInputStream()); } catch (EOFException e) { // 空输入流时返回空字节流 this.inputStream = new ByteArrayInputStream(new byte[0]); } catch (Exception e) { e.printStackTrace(); // 异常时回退到原输入流 this.inputStream = request.getInputStream(); } } @Override public InputStream getInputStream() throws IOException { return inputStream; } // 重写该方法,返回原请求的Content-Type @Override public String getContentType() { return super.getContentType(); } // 确保Content-Type头能被正确获取 @Override public String getHeader(String name) { if ("Content-Type".equalsIgnoreCase(name)) { return super.getHeader(name); } return super.getHeader(name); } }
3. 修正过滤器的doFilter逻辑
仅对带有Content-Encoding: gzip头的请求使用包装器,避免影响正常非压缩请求:
public class GzipRequestFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpRequest = (HttpServletRequest) request; String contentEncoding = httpRequest.getHeader("Content-Encoding"); if (contentEncoding != null && contentEncoding.equalsIgnoreCase("gzip")) { chain.doFilter(new GzippedInputStreamWrapper(httpRequest), response); } else { chain.doFilter(request, response); } } @Override public void init(FilterConfig filterConfig) throws ServletException {} @Override public void destroy() {} }
4. 注册过滤器到Spring Boot
通过@Component注解直接注册过滤器:
@Component public class GzipRequestFilter implements Filter { // 上述doFilter等方法 }
修复原理
- Angular端指定Blob的
type后,请求的Content-Type会被正确设置为application/json,Content-Encoding: gzip则告诉后端需要解压内容。 - Spring的请求包装器重写相关方法后,Spring MVC能正确识别请求的内容类型,匹配控制器的
consumes = "application/json"条件,自动将解压后的JSON映射到UserDTO参数。
内容的提问来源于stack exchange,提问作者Ana Belén González Villalba
相关产品推荐
相关产品推荐

