Add ResourceRegionEncoder

This commit adds the necessary infrastructure for the support of HTTP
Range requests. The new `ResourceRegionEncoder` can write
`ResourceRegion` objects as streams of bytes.

The `ResourceRegionEncoder` relies on an encoding hint
`BOUNDARY_STRING_HINT`. If present, the encoder infers that multiple
`ResourceRegion`s should be encoded and that the provided boundary
String should be used to separate ranges by mime boundaries.
If that hint is absent, only a single resource region is encoded.

Issue: SPR-14664
This commit is contained in:
Brian Clozel
2016-09-12 12:18:56 +02:00
parent 1d46b8d7e1
commit 55d6f88dcd
6 changed files with 385 additions and 16 deletions

View File

@@ -28,13 +28,13 @@ import reactor.core.publisher.Mono;
import org.springframework.core.ResolvableType;
import org.springframework.core.codec.ResourceDecoder;
import org.springframework.core.codec.ResourceEncoder;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.MediaTypeFactory;
import org.springframework.http.ReactiveHttpOutputMessage;
import org.springframework.http.ZeroCopyHttpOutputMessage;
import org.springframework.util.ResourceUtils;
/**
* Implementation of {@link HttpMessageWriter} that can write
@@ -81,7 +81,7 @@ public class ResourceHttpMessageWriter extends EncoderHttpMessageWriter<Resource
headers.setContentType(mediaType);
}
if (headers.getContentLength() < 0) {
contentLength(resource).ifPresent(headers::setContentLength);
ResourceUtils.contentLength(resource).ifPresent(headers::setContentLength);
}
}
@@ -101,19 +101,6 @@ public class ResourceHttpMessageWriter extends EncoderHttpMessageWriter<Resource
outputMessage.getHeaders().getContentType(), outputMessage, hints);
}
private static Optional<Long> contentLength(Resource resource) {
// Don't try to determine contentLength on InputStreamResource - cannot be read afterwards...
// Note: custom InputStreamResource subclasses could provide a pre-calculated content length!
if (InputStreamResource.class != resource.getClass()) {
try {
return Optional.of(resource.contentLength());
}
catch (IOException ignored) {
}
}
return Optional.empty();
}
private static Optional<File> getFile(Resource resource) {
if (resource.isFile()) {
try {