繁体   English   中英

如何最好地从 Spring WebClient 的 ClientResponse 获取字节数组?

[英]How to best get a byte array from a ClientResponse from Spring WebClient?

我正在使用响应式编程的代码库中尝试使用 Spring 5 (5.0.0.RC2) 中的新WebClient ,并且我已经成功地将 JSON 响应从端点映射到我的应用程序中的 DTO,效果非常好:

WebClient client = WebClient.create(baseURI);
Mono<DTO> dto = client.get()
        .uri(uri)
        .accept(MediaType.APPLICATION_JSON)
        .exchange()
        .flatMap(response -> response.bodyToMono(DTO.class));

但是,现在我正在尝试从使用协议缓冲区(二进制数据用作application/octet-stream )的端点获取响应正文,因此我想从响应中获取原始字节,然后将其映射自己一个对象。

我使用来自 Google Guava 的Bytes让它像这样工作:

Mono<byte[]> bytes = client.get()
        .uri(uri)
        .accept(MediaType.APPLICATION_OCTET_STREAM)
        .exchange()
        .flatMapMany(response -> response.body(BodyExtractors.toDataBuffers()))
        .map(dataBuffer -> {
            ByteBuffer byteBuffer = dataBuffer.asByteBuffer();
            byte[] byteArray = new byte[byteBuffer.remaining()];
            byteBuffer.get(byteArray, 0, bytes.length);
            return byteArray;
        })
        .reduce(Bytes::concat)

这是有效的,但是有没有更简单、更优雅的方法来获取这些字节?

ClientResponse.bodyToMono()最终使用了一些声称支持指定类的org.springframework.core.codec.Decoder

所以我们应该检查Decoder的类层次结构,特别是decodeToMono()方法的实现位置和方式。

有一个StringDecoder支持解码为String ,一堆与 Jackson 相关的解码器(在你的 DTO 示例中使用),还有一个ResourceDecoder是特别有趣的。

ResourceDecoder支持org.springframework.core.io.InputStreamResourceorg.springframework.core.io.ByteArrayResource ByteArrayResource本质上是byte[]的包装器,因此以下代码将提供对作为字节数组的响应主体的访问:

Mono<byte[]> mono = client.get()
            ...
            .exchange()
            .flatMap(response -> response.bodyToMono(ByteArrayResource.class))
            .map(ByteArrayResource::getByteArray);

Oleg Estekhin 的回答为 OP 提供了他所要求的内容,但它将整个响应内容加载到内存中,这对于大型响应来说是一个问题。 要一次获取一大块字节,我们可以执行以下操作:

client.get()
  .uri("uri")
  .exchange()
  .flatMapMany { it.body(BodyExtractors.toDataBuffers()) }

默认情况下,这些缓冲区的大小为 8192 kb; 如果需要,请参阅答案以进行更改。

请注意,如果ByteBuffer不受数组支持,则尝试执行dataBuffer.asByteBuffer().array()会引发异常。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM