将写入转换为OutputStream为ServerResponse可用的Flux <databuffer>

时间:2018-03-22 10:30:04

标签: spring-webflux

我有一个遗留库,我必须用它来检索文件。这个遗留库不会在InputStream中返回,正如您通常期望的那样读取内容,但它期望它传递一个打开的OutputStream,它可以写入。

我必须编写一个Webflux REST服务,它将此OutputStream写入org.springframework.web.reactive.function.server.ServerResponse正文。

legacyLib.BlobRead(outputStream); // writes the stream to an outputstream, that has to be provided by me, and somehow has to end up in the ServerResponse

由于我想将Stream直接传递给ServerResponse,我可能不得不做这样的事情,对吗?

ServerResponse.ok().body(magicOutpuStreamToFluxConverter(), DataBuffer.class);

1 个答案:

答案 0 :(得分:0)

这里的RequestHandler的一部分非常重要;我遗漏了一些错误处理/捕获异常,通常可能不需要。请注意,我发布了一个不同的调度程序用于读取(或者至少是我想要做的事情),因此这个阻塞读取不会干扰我的主事件线程:

private Mono<ServerResponse> writeToServerResponse(@NotNull FPTag tag) {
    final long blobSize = tag.getBlobSize();
    return ServerResponse.ok()
        .contentType(MediaType.APPLICATION_OCTET_STREAM)
        .body(Flux.<DataBuffer>create((FluxSink<DataBuffer> emitter) -> {
      // for a really big blob I want to read it in chunks, so that my server doesn't use too much memory
      for(int i = 0; i < blobSize; i+= tagChunkSize) {
        // new DataBuffer that is written to, then emitted later
        DefaultDataBuffer dataBuffer = new DefaultDataBufferFactory().allocateBuffer();
        try (OutputStream outputStream = dataBuffer.asOutputStream()) {
          // write to the outputstream of DataBuffer
          tag.BlobReadPartial(outputStream, i, tagChunkSize, FPLibraryConstants.FP_OPTION_DEFAULT_OPTIONS);
          // don't know if flushing is strictly neccessary
          outputStream.flush();
        } catch (IOException | FPLibraryException e) {
          log.error("Error reading + writing from tag to http outputstream", e);
          emitter.error(e);
        }
        emitter.next(dataBuffer);
      }
      // if blob is finished, send "complete" to my flux of DataBuffers
      emitter.complete();
    }, FluxSink.OverflowStrategy.BUFFER).publishOn(Schedulers.newElastic("centera")).doOnComplete(() -> closeQuietly(tag)), DataBuffer.class);

}