Skip to content

Commit 4e2fb30

Browse files
committed
Document contentLength() behavior for InputStreamResource and custom subclasses
Closes gh-33089
1 parent 5f765fc commit 4e2fb30

File tree

2 files changed

+12
-3
lines changed

2 files changed

+12
-3
lines changed

framework-docs/modules/ROOT/pages/web/webmvc/mvc-controller/ann-methods/responseentity.adoc

+3-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@ content of the provided resource to the response `OutputStream`. Note that the
4040
`InputStream` should be lazily retrieved by the `Resource` handle in order to reliably
4141
close it after it has been copied to the response. If you are using `InputStreamResource`
4242
for such a purpose, make sure to construct it with an on-demand `InputStreamSource`
43-
(e.g. through a lambda expression that retrieves the actual `InputStream`).
43+
(e.g. through a lambda expression that retrieves the actual `InputStream`). Also, custom
44+
subclasses of `InputStreamResource` are only supported in combination with a custom
45+
`contentLength()` implementation which avoids consuming the stream for that purpose.
4446

4547
Spring MVC supports using a single value xref:web/webmvc/mvc-ann-async.adoc#mvc-ann-async-reactive-types[reactive type]
4648
to produce the `ResponseEntity` asynchronously, and/or single and multi-value reactive

spring-core/src/main/java/org/springframework/core/io/InputStreamResource.java

+9-2
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,13 @@
4040
* times. This also applies when constructed with an {@code InputStreamSource}
4141
* which lazily obtains the stream but only allows for single access as well.
4242
*
43+
* <p><b>NOTE: This class does not provide an independent {@link #contentLength()}
44+
* implementation: Any such call will consume the given {@code InputStream}!</b>
45+
* Consider overriding {@code #contentLength()} with a custom implementation if
46+
* possible. For any other purpose, it is not recommended to extend from this
47+
* class; this is particularly true when used with Spring's web resource rendering
48+
* which specifically skips {@code #contentLength()} for this exact class only.
49+
*
4350
* @author Juergen Hoeller
4451
* @author Sam Brannen
4552
* @since 28.12.2003
@@ -132,8 +139,8 @@ public boolean isOpen() {
132139
@Override
133140
public InputStream getInputStream() throws IOException, IllegalStateException {
134141
if (this.read) {
135-
throw new IllegalStateException("InputStream has already been read - " +
136-
"do not use InputStreamResource if a stream needs to be read multiple times");
142+
throw new IllegalStateException("InputStream has already been read (possibly for early content length " +
143+
"determination) - do not use InputStreamResource if a stream needs to be read multiple times");
137144
}
138145
this.read = true;
139146
return this.inputStreamSource.getInputStream();

0 commit comments

Comments
 (0)