Cannot read Part's content (Flux<DataBuffer>) into a single String

Viewed 4387

In the following snippet, I'm trying to extract a file's content (sent to a given service) using Spring's Part object and convert it into a String.

The issue is that it skips the mapper function and the code inside the mapper function doesn't execute like the filePartMono's content is empty, but when I inspect the object at runtime , its storage field has the file's data.

public void parseFilePart(Part filePartMono) {
    filePartMono.content().map(dataBuffer -> {
            byte[] bytes = new byte[dataBuffer.readableByteCount()];
            dataBuffer.read(bytes);
            DataBufferUtils.release(dataBuffer);
            String fileContent = new String(bytes, StandardCharsets.UTF_8);
        });
}
1 Answers

org.springframework.http.codec.multipart.Part.content() returns a Flux<DataBuffer>, meaning nothing happens until you subscribe to this Publisher.

If your code can be executed in a blocking way without causing errors, you can refactor it like this to get the String result:

public void parseFilePart(Part filePartMono) {
  List<String> parts = 
    filePartMono.content()
    .map(dataBuffer -> {
          byte[] bytes = new byte[dataBuffer.readableByteCount()];
          dataBuffer.read(bytes);
          DataBufferUtils.release(dataBuffer);
          return new String(bytes, StandardCharsets.UTF_8);
    })
    .collectList()
    .block();
  //do what you want here with the Strings you retrieved
}

If you're sure that the Flux<DataBuffer> will always emit 1 single DataBuffer, you can replace .collectList().block() with .blockFirst() and obtain a String result instead of List<String>.

If your code can't be executed in a blocking fashion, then you could refactor it like this:

public void parseFilePart(Part filePartMono) {
    filePartMono.content()
    .map(dataBuffer -> {
          byte[] bytes = new byte[dataBuffer.readableByteCount()];
          dataBuffer.read(bytes);
          DataBufferUtils.release(dataBuffer);
          return new String(bytes, StandardCharsets.UTF_8);
    })
    .subscribe(resultString -> {
      //do what you want with the result String here
    });
}

P.S. I didn't test your implementation to convert DataBuffer to String, so you might have to double-check that now that it's actually invoked

Related