当前位置: 首页 > 知识库问答 >
问题:

如何解压缩Flux(以及如何编写一个)?

颛孙俊
2023-03-14

我需要在没有中间存储的情况下读写压缩(GZIP)流。目前,我使用Springrestemplate进行编写,使用Apache-HTTP-client进行读取(有关restemplate不能用于读取大数据流的原因的解释,请参阅我的回答)。实现相当简单,我在响应上加了一个gzip输入流,然后继续。

现在,我想转而使用Spring5WebClient(只是因为我不喜欢现状)。然而,WebClient本质上是被动的,处理流量

  • 另见ReactorNetty第251期

我承认对(去)压缩知之甚少,但是,我做了我的研究,但是网上可用的材料似乎都没有特别有用。

java nio直接缓冲区上的压缩

用nio编写GZIP文件

从FileChannel(JavaNIO)读取GZIP文件

(de)使用NIO压缩文件

可迭代gzip在Java中放气/充气


共有2个答案

丁钟展
2023-03-14

注意这一点,因为它让我有点困惑-API从5.1开始有点变化。

我有一个类似于ChannelInboundHandler的公认答案的设置:

public class GzipJsonHeadersHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        if (msg instanceof HttpResponse
                && !HttpStatus.resolve(((HttpResponse) msg).status().code()).is1xxInformational()) {
            HttpHeaders headers = ((HttpResponse) msg).headers();
            headers.clear();
            headers.set(HttpHeaderNames.CONTENT_ENCODING, HttpHeaderValues.GZIP);
            headers.set(HttpHeaderNames.CONTENT_TYPE, HttpHeaderValues.APPLICATION_JSON);
        }
        ctx.fireChannelRead(msg);
    }
}

(为了简单起见,我需要的标题值只是在那里硬编码的,否则它是相同的。)

然而,注册它是不同的:

WebClient.builder()
    .clientConnector(
            new ReactorClientHttpConnector(
                    HttpClient.from(
                            TcpClient.create()
                                    .doOnConnected(c -> {
                                        c.addHandlerFirst(new HttpContentDecompressor());
                                        c.addHandlerFirst(new HttpResponseHeadersHandler());
                                    })
                    ).compress(true)
            )
    )
    .build();

Netty现在似乎在系统列表之外(和之后)维护一个处理程序的用户列表,并且只将处理程序放在用户列表的前面。因此,它需要显式调用HttpContentDecompressor,以确保它在插入正确头的处理程序之后明确执行。

汪迪
2023-03-14
public class HttpResponseHeadersHandler extends ChannelInboundHandlerAdapter {
    private final HttpHeaders httpHeaders;

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        if (msg instanceof HttpResponse &&
                !HttpStatus.resolve(((HttpResponse) msg).status().code()).is1xxInformational()) {
            HttpHeaders headers = ((HttpResponse) msg).headers();

            httpHeaders.forEach(e -> {
                log.warn("Modifying {} from: {} to: {}.", e.getKey(), headers.get(e.getKey()), e.getValue());
                headers.set(e.getKey(), e.getValue());
            });
        }
        ctx.fireChannelRead(msg);
    }
}

然后我创建一个ClientHttpConnectorWebClient一起使用,并在NettyContextInit之后添加处理程序:

ctx.addHandlerLast(new ReadTimeoutHandler(readTimeoutMillis, TimeUnit.MILLISECONDS));
ctx.addHandlerLast(new Slf4JLoggingHandler());
if (forceDecompression) {
    io.netty.handler.codec.http.HttpHeaders httpHeaders = new ReadOnlyHttpHeaders(
            true,
            CONTENT_ENCODING, GZIP,
            CONTENT_TYPE, APPLICATION_JSON
    );
    HttpResponseHeadersHandler headersModifier = new HttpResponseHeadersHandler(httpHeaders);
    ctx.addHandlerFirst(headersModifier);
}
ctx.addHandlerLast(new HttpContentDecompressor());

当然,对于没有经过GZIP压缩的响应,这将失败,因此我仅将这个WebClient实例用于特定用例,我确信响应是压缩的。

编写很容易:Spring有一个资源编码器,因此可以简单地将InputStream转换为InputStreamResource,瞧!

 类似资料:
  • 问题内容: 我需要在没有中间存储的情况下读写压缩(GZIP)流。目前,我正在使用Spring 进行编写,而使用Apache HTTP客户端来进行阅读的答案,以解释为什么不能用于读取大数据流)。实现是相当简单的,我在响应上打了一下然后继续。 现在,我想切换到使用Spring 5 WebClient(只是因为我不喜欢现状)。但是,本质上是反应性的,并且要处理;我相信有可能获得,其中DataBuffer

  • 保存zip附件的ruby代码: 在我的本地计算机(OS X)上运行的文件可以很好地工作,但是在远程计算机(CentOS)上,相同的命令会产生一个错误: 未找到中央目录结束签名。要么这个文件不是zipfile,要么它构成了多部分归档的一个磁盘。在后一种情况下,中央目录和zipfile注释将在这个归档的最后一个磁盘上找到。 编辑: 在我的本地计算机上,给了我Zip归档数据,至少要提取V2.0版本。我的

  • 问题内容: 我需要一个小的代码片段,该片段从给定的.zip文件中解压缩一些文件,并根据压缩文件中的格式提供单独的文件。请发表您的知识并帮助我。 问题答案: peno的版本进行了优化。性能的提高是可以察觉的。

  • 问题内容: 我已经使用follwoing命令打包了我的电子应用程序 现在,我需要将其解压缩并重新获得整个代码。反正有这样做吗? 问题答案: 从asar文档 (此处的用法是避免使用全局安装该工具) 提取整个档案: 提取特定文件:

  • 我有一个JSON文件,它是。 我可以使用下载压缩文件。

  • 问题内容: 我已经找到了许多有关如何从.zip中提取 所有 文件的示例,但是我不知道如何在不迭代.zip文件中的所有文件的情况下提取单个文件。 Go中是否可以从.zip存档中提取单个文件,而无需遍历.zip文件中的所有文件? 例如,如果一个zip文件包含: 我将只提取 吗? 问题答案: 为您提供的归档文件的内容,这些文件作为 片 (的)。没有通过名称获取文件的帮助程序方法,您必须使用循环来遍历文件