Reuse InputStream in ResourceRegionHttpMessageConverter

The converter now tries to keep reading from the same InputStream which
should be possible with ordered and non-overlapping regions. When
necessary the InputStream is re-opened.

Closes gh-24214
This commit is contained in:
Rossen Stoyanchev
2019-12-18 16:22:04 +00:00
parent 7474ee7041
commit 0eacb443b0
3 changed files with 70 additions and 14 deletions

View File

@@ -179,11 +179,23 @@ public class ResourceRegionHttpMessageConverter extends AbstractGenericHttpMessa
responseHeaders.set(HttpHeaders.CONTENT_TYPE, "multipart/byteranges; boundary=" + boundaryString);
OutputStream out = outputMessage.getBody();
for (ResourceRegion region : resourceRegions) {
long start = region.getPosition();
long end = start + region.getCount() - 1;
InputStream in = region.getResource().getInputStream();
try {
Resource resource = null;
InputStream in = null;
long inputStreamPosition = 0;
try {
for (ResourceRegion region : resourceRegions) {
long start = region.getPosition() - inputStreamPosition;
if (start < 0 || resource != region.getResource()) {
if (in != null) {
in.close();
}
resource = region.getResource();
in = resource.getInputStream();
inputStreamPosition = 0;
start = region.getPosition();
}
long end = start + region.getCount() - 1;
// Writing MIME header.
println(out);
print(out, "--" + boundaryString);
@@ -193,20 +205,25 @@ public class ResourceRegionHttpMessageConverter extends AbstractGenericHttpMessa
println(out);
}
Long resourceLength = region.getResource().contentLength();
end = Math.min(end, resourceLength - 1);
print(out, "Content-Range: bytes " + start + '-' + end + '/' + resourceLength);
end = Math.min(end, resourceLength - inputStreamPosition - 1);
print(out, "Content-Range: bytes " +
region.getPosition() + '-' + (region.getPosition() + region.getCount() - 1) +
'/' + resourceLength);
println(out);
println(out);
// Printing content
StreamUtils.copyRange(in, out, start, end);
inputStreamPosition += (end + 1);
}
finally {
try {
}
finally {
try {
if (in != null) {
in.close();
}
catch (IOException ex) {
// ignore
}
}
catch (IOException ex) {
// ignore
}
}