jfinal开启gzip导致下载文件无content-length问题

由于jfinal开启gzip导致返回头部content-length为0从而导致小程序获取进度失败问题

  1. 问题原因

gzip会使得content-length不生效,因为服务器认为如果你开启了gzip最后的压缩结果和你提供的length将会不一致,所以会移除content-length

  1. 处理方法分析
//UndertowServer类中存在此方法
protected HttpHandler configGzip(HttpHandler pathHandler) {
        if (config.isGzipEnable()) {
           //undertow使用HttpHandler 做为请求处理链,而如果开启了gzip则加入EncodingHandler处理器
          //ContentEncodingRepository 中便是最终判断是否需要处理gzip
            ContentEncodingRepository repository = new ContentEncodingRepository();
            GzipEncodingProvider provider = new GzipEncodingProvider(config.getGzipLevel());
            int minLength = config.getGzipMinLength();
            Predicate predicate = minLength > 0 ? Predicates.maxContentSize(minLength) : Predicates.truePredicate();
            repository.addEncodingHandler("gzip", provider, 100, predicate);
            return new EncodingHandler(pathHandler, repository);
        }
        return pathHandler;
    }
}

由上得出两种处理方式1.在ContentEncodingRepository处扩展做手脚2.HttpHandler 处做手脚.

  1. 处理办法1
    protected HttpHandler configGzip(HttpHandler pathHandler) {
        if (config.isGzipEnable()) {
            ContentEncodingRepository repository = new ContentEncodingRepositoryExt();
            GzipEncodingProvider provider = new GzipEncodingProvider(config.getGzipLevel());
            int minLength = config.getGzipMinLength();
            Predicate predicate = minLength > 0 ? Predicates.maxContentSize(minLength) : Predicates.truePredicate();
            repository.addEncodingHandler("gzip", provider, 100, predicate);
            return new EncodingHandler(pathHandler, repository);
        }
        return pathHandler;
    }

复写UndertowServer重写configGzip,并且新建io.undertow.server.handlers.encoding.ContentEncodingRepository#getContentEncodings子类复写getContentEncodings方法,在处理前判断当前请求的url是否需要过滤,如果过滤则返回null,否则继续执行gzip后续代码.

  1. 处理办法2
//复写UndertowServer重写configGzip,并且新建HttpHandler 的子类FileHttpHandler 
  protected HttpHandler configGzip(HttpHandler pathHandler) {
        return new FileHttpHandler(super.configGzip(pathHandler));
    }
//在FileHttpHandler 内部处理掉由getContentEncodings方法使用的ACCEPT_ENCODING,便可实现
   public void handleRequest(HttpServerExchange exchange) throws Exception {
        if (exchange.getRequestURI().startsWith("/file")){
            exchange.getRequestHeaders().remove(Headers.ACCEPT_ENCODING);
        }
        next.handleRequest(exchange);
    }

笔者采用第二种因为代码少,更容易理解.

推荐阅读更多精彩内容