Netty 4中ChunkedWriteHandler与HttpContentCompressor冲突导致不压缩的问题

如果ChunkedWriteHandler与HttpContentCompressor都使用,在传递文件会忽略掉HttpContentCompressor导致内容并没有压缩,所以重载HttpContentCompressor使得它可以与ChunkedWriteHandler配合使用。

以下代码中重载write函数将msg包装成HttpContent使得内容可以被压缩,同时重载beginEncode只容许压缩几种常见的类型,其他类型都放弃压缩,比如jpg、png等本身已经压缩过,再次压缩只会增大体积。

public class HttpChunkableContentCompressor extends HttpContentCompressor {
    private static final String[] COMPRESSABLE = new String[] {
        "/javascript", "text/css", "text/html", "text/plain", "text/csv"};
   
    public HttpChunkableContentCompressor(int min, CompressionOptions... compressionOptions) {
        super(min, compressionOptions);
    }

    @Override
    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
        Object m = msg;
        if (msg instanceof ByteBuf) {
            /*
             * 将ByteBuf转换为HttpContent,
             * 使其能够使传递给HttpContentCompressor,
             * 否则,在有ChunkedWriteHandler时,无法压缩文件
             */
            ByteBuf buf = (ByteBuf) msg;
            
            if (buf.isReadable()) {
                //只编码非空缓冲区,因为空缓冲区可用于确定内容何时被刷新
                m = new DefaultHttpContent(buf);
            }
        }
        super.write(ctx, m, promise);
    }
    
//注意以下代码与网上其他解决方案不同,重载beginEncode过滤掉无需压缩的文件类型
    @Override
    protected Result beginEncode(HttpResponse headers, String acceptEncoding) throws Exception {
        String contentType = headers.headers().get(HttpUtil.HEAD_CONTENT_TYPE);
        char c = contentType.charAt(0);
        if(c == 't' || c == 'a') { //text or application
            for(String ct : COMPRESSABLE) {
                if(contentType.contains(ct)) {
                    return super.beginEncode(headers, acceptEncoding);
                }
            }
        }
        //Needn't, return null to disable compression
        return null;
    }
}

最后在pipeline中添加handler

ChannelPipeline pl = ctx.pipeline();
pl.addLast("http2_codec", builder.build());
//pl.addLast("aggregator", new HttpObjectAggregator(MAX_CONTENT_LENGTH));//无需聚集,h2在AbsServerRequest中完成
pl.addLast("compressor", new HttpChunkableContentCompressor(MIN_COMPRESS_LENGTH, new CompressionOptions[0]));
//提供chunk方式文件下载,比如DownloadLog中
pl.addLast("chunkedWriter", new ChunkedWriteHandler());
pl.addLast("http2_handler", http2ServerHandler);

最近(2023.5)发现在安卓环境,压缩不能使用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值