title: In Spring Webflux how to go from an `OutputStream` to a `Flux<DataBuffer>`?
body: <p>I'm building a tarball dynamically, and would like to stream it back directly, which should be 100% possible with a .tar.gz.</p>
  
  <p>The below code is the closest thing I could get to a dataBuffer, through lots of googling. Basically, I need something that implements an <code>OutputStream</code> and provides, or publishes, to a <code>Flux&lt;DataBuffer&gt;</code> so that I can return that from my method, and have streaming output, instead of buffering the entire tarball in ram (which I'm pretty sure is what is happening here). I'm using apache Compress-commons, which has a wonderful API, but it's all OutputStream based.</p>
  
  <p>I suppose another way to do it would be to directly write to the response, but I don't think that would be properly reactive? Not sure how to get an <code>OutputStream</code> out of some sort of Response object either.</p>
  
  <p>This is kotlin btw, on Spring Boot 2.0</p>
  
  <pre><code>@GetMapping("/cookbook.tar.gz", "/cookbook")
  fun getCookbook(): Mono&lt;DefaultDataBuffer&gt; {
      log.info("Creating tarball of cookbooks: ${soloConfig.cookbookPaths}")
  
      val transformation = Mono.just(soloConfig.cookbookPaths.stream()
              .toList()
              .flatMap {
                  Files.walk(Paths.get(it)).map(Path::toFile).toList()
              })
              .map { files -&gt;
  
                  //Will make one giant databuffer... but oh well? TODO: maybe use some kind of chunking.
                  val buffer = DefaultDataBufferFactory().allocateBuffer()
                  val outputBufferStream = buffer.asOutputStream()
  
  
                  //Transform my list of stuff into an archiveOutputStream
                  TarArchiveOutputStream(GzipCompressorOutputStream(outputBufferStream)).use { taos -&gt;
                      taos.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU)
  
                      log.info("files to compress: ${files}")
  
                      for (file in files) {
                          if (file.isFile) {
                              val entry = "cookbooks/" + file.name
                              log.info("Adding ${entry} to tarball")
                              taos.putArchiveEntry(TarArchiveEntry(file, entry))
                              FileInputStream(file).use { fis -&gt;
                                  fis.copyTo(taos) //Copy that stuff!
                              }
                              taos.closeArchiveEntry()
                          }
                      }
                  }
                  buffer
              }
  
      return transformation
  }
  </code></pre>