복붙노트

[SPRING] Flux <DataBuffer>의 압축을 해제하는 방법 (및 작성 방법)

SPRING

Flux 의 압축을 해제하는 방법 (및 작성 방법)

중간 저장 공간없이 압축 된 (GZIP) 스트림을 읽고 쓸 수있는 요구 사항이 있습니다. 현재 저는 Spring RestTemplate을 사용하여 글을 쓰고 있고 아파치 HTTP 클라이언트는 읽기를하고 있습니다. (왜 RestTemplate이 큰 스트림을 읽을 수 없는지에 대한 내 대답을보십시오). 구현은 상당히 직설적인데, 응답 InputStream에서 GZIPInputStream을 쳐서 계속 진행합니다.

이제 Spring 5 WebClient (단순히 내가 현 상태에 대한 팬이 아니기 때문에)로 전환하고 싶습니다. 그러나 WebClient는 본질적으로 반응적이고 Flux 를 처리합니다. 나는 DataBuffer가 ByteBuffer에 대한 추상화 인 Flux 를 얻는 것이 가능하다고 믿는다. 질문은, 전체 메모리를 메모리에 저장하지 않고도 (OutOfMemoryError, 찾고 있어요) 로컬 디스크에 쓰지 않고 즉시 압축을 풀 수 있습니까? NetClient가 Netty를 사용한다고 언급 할 가치가 있습니다.

나는 (압축) 압축에 대해 많이 알지 못한다는 것을 인정하지만, 나는 나의 연구를했다. 그러나 온라인으로 구할 수있는 자료는 특별히 도움이되지 못했다.

java nio 직접 버퍼 압축

nio로 GZIP 파일 작성하기

FileChannel (Java NIO)에서 GZIP 파일 읽기

NIO를 사용하여 파일 압축하기

반복 가능한 gzip은 Java에서 수축 / 팽창합니다.

해결법

  1. ==============================

    1.

    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);
        }
    }
    

    그런 다음 WebClient와 함께 사용할 ClientHttpConnector를 만들고 afterNettyContextInit에서 처리기를 추가합니다.

    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은 ResourceEncoder를 가지고있어서 InputStream은 단순히 InputStreamResource로 변환 될 수 있습니다.

  2. from https://stackoverflow.com/questions/48046007/how-to-decompress-a-fluxdatabuffer-and-how-to-write-one by cc-by-sa and MIT license