I am using URL class to read an InputStream from it. Is there any way I can use RestTemplate for this?
InputStream input = new URL(url).openStream();
JsonReader reader = new JsonReader(new InputStreamReader(input, StandardCharsets.UTF_8.displayName()));
How can I get InputStream
with RestTemplate
instead of using URL
?
The previous answers are not wrong, but they don't go into the depth that I like to see. There are cases when dealing with low level InputStream
is not only desirable, but necessary, the most common example being streaming a large file from source (some web server) to destination (a database). If you try to use a ByteArrayInputStream
, you will be, not so surprisingly, greeted with OutOfMemoryError
. Yes, you can roll your own HTTP client code, but you'll have to deal with erroneous response codes, response converters etc. If you are already using Spring, looking to RestTemplate
is a natural choice.
As of this writing, spring-web:5.0.2.RELEASE
has a ResourceHttpMessageConverter
that has a boolean supportsReadStreaming
, which if set, and the response type is InputStreamResource
, returns InputStreamResource
; otherwise it returns a ByteArrayResource
. So clearly, you're not the only one that asked for streaming support.
However, there is a problem: RestTemplate
closes the response soon after the HttpMessageConverter
runs. Thus, even if you asked for InputStreamResource
, and got it, it's no good, because the response stream has been closed. I think this is a design flaw that they overlooked; it should've been dependent on the response type. So unfortunately, for reading, you must consume the response fully; you can't pass it around if using RestTemplate
.
Writing is no problem though. If you want to stream an InputStream
, ResourceHttpMessageConverter
will do it for you. Under the hood, it uses org.springframework.util.StreamUtils
to write 4096 bytes at a time from the InputStream
to the OutputStream
.
Some of the HttpMessageConverter
support all media types, so depending on your requirement, you may have to remove the default ones from RestTemplate
, and set the ones you need, being mindful of their relative ordering.
Last but not the least, implementations of ClientHttpRequestFactory
has a boolean bufferRequestBody
that you can, and should, set to false
if you are uploading a large stream. Otherwise, you know, OutOfMemoryError
. As of this writing, SimpleClientHttpRequestFactory
(JDK client) and HttpComponentsClientHttpRequestFactory
(Apache HTTP client) support this feature, but not OkHttp3ClientHttpRequestFactory
. Again, design oversight.
Edit: Filed ticket SPR-16885.