ResourceHttpMessageConverter class method readInternal create InputStreamResource only when we use InputStreamResource in controller method, otherwice it create ByteArrayResource. I think it's incorrect, and we need write something like this, see code below. Or someone can explain why it created in that way?
@Override
protected Resource readInternal(Class<? extends Resource> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException {
if (this.supportsReadStreaming && (InputStreamResource.class == clazz || Resource.class == clazz)) {
return new InputStreamResource(inputMessage.getBody()) {
@Override
public String getFilename() {
return inputMessage.getHeaders().getContentDisposition().getFilename();
}
@Override
public long contentLength() throws IOException {
long length = inputMessage.getHeaders().getContentLength();
return (length != -1 ? length : super.contentLength());
}
};
} else if (ByteArrayResource.class.isAssignableFrom(clazz)) {
byte[] body = StreamUtils.copyToByteArray(inputMessage.getBody());
return new ByteArrayResource(body) {
@Override
@Nullable
public String getFilename() {
return inputMessage.getHeaders().getContentDisposition().getFilename();
}
};
} else {
throw new HttpMessageNotReadableException("Unsupported resource class: " + clazz, inputMessage);
}
}
Comment From: bclozel
This is selecting InputStreamResource
only if streaming is supported (in the case RestTemplate
, streaming is not supported) and the target type is InputStreamResource
. The Javadoc of InputStreamResource
states why it should only be used in some cases.
Applying the change you've suggested would:
- prevent developers from reading the stream multiple times
- force them to properly drain and close the stream, otherwise the state of the HTTP connection would be invalid and would need to be closed.
- break many applications out there if they're not dealing with 1) and 2) properly
Comment From: ainGitHub
@bclozel thanks for the explanation. I assume that for my application, I can just create my own resourceConverter and use it without changing the implementations from Resource to InputStreamResource. By the way, there is a similar question for ResourceDecoder. There, in the decode method, for some reason, for InputStreamResource, data is created from ByteArrayInputStream. Whether it is impossible to implement receiving of the data from DataBuffer in a stream form there?
Comment From: bclozel
By the way, there is a similar question for ResourceDecoder. There, in the decode method, for some reason, for InputStreamResource, data is created from ByteArrayInputStream. Whether it is impossible to implement receiving of the data from DataBuffer in a stream form there?
In this case, the data here is already read in memory as a DataBuffer
, so there is no InputStream
to plug in. The data should be read in a non-blocking fashion, so InputStream
do not work there. If you wish to read asynchronously, Flux<DataBuffer>
is a better choice there.
I'm closing this issue as the matter seems to be resolved. Thanks!