diff --git a/core/src/main/java/io/undertow/io/BufferWritableOutputStream.java b/core/src/main/java/io/undertow/io/BufferWritableOutputStream.java index 63ca9a9d88..b22be4086a 100644 --- a/core/src/main/java/io/undertow/io/BufferWritableOutputStream.java +++ b/core/src/main/java/io/undertow/io/BufferWritableOutputStream.java @@ -34,6 +34,10 @@ public interface BufferWritableOutputStream { void write(ByteBuffer byteBuffer) throws IOException; + /** + * Transfer the remaining content of the input FileChannel (from its current position, to end of file). + */ + @Deprecated void transferFrom(FileChannel source) throws IOException; } diff --git a/core/src/main/java/io/undertow/io/UndertowOutputStream.java b/core/src/main/java/io/undertow/io/UndertowOutputStream.java index 22b7b49709..68f974875c 100644 --- a/core/src/main/java/io/undertow/io/UndertowOutputStream.java +++ b/core/src/main/java/io/undertow/io/UndertowOutputStream.java @@ -309,6 +309,8 @@ private void writeBufferBlocking(final boolean writeFinal) throws IOException { @Override public void transferFrom(FileChannel source) throws IOException { + final long startPosition = source.position(); + final long count = source.size() - source.position(); if (anyAreSet(state, FLAG_CLOSED)) { throw UndertowMessages.MESSAGES.streamIsClosed(); } @@ -318,10 +320,8 @@ public void transferFrom(FileChannel source) throws IOException { if (channel == null) { channel = exchange.getResponseChannel(); } - long position = source.position(); - long size = source.size(); - Channels.transferBlocking(channel, source, position, size); - updateWritten(size - position); + Channels.transferBlocking(channel, source, startPosition, count); + updateWritten(count); } /** diff --git a/servlet/src/main/java/io/undertow/servlet/spec/ServletOutputStreamImpl.java b/servlet/src/main/java/io/undertow/servlet/spec/ServletOutputStreamImpl.java index 93171c3426..30b79e4a25 100644 --- a/servlet/src/main/java/io/undertow/servlet/spec/ServletOutputStreamImpl.java +++ b/servlet/src/main/java/io/undertow/servlet/spec/ServletOutputStreamImpl.java @@ -556,7 +556,12 @@ public void transferFrom(FileChannel source) throws IOException { if (anyAreSet(state, FLAG_CLOSED) || servletRequestContext.getOriginalResponse().isTreatAsCommitted()) { throw UndertowServletMessages.MESSAGES.streamIsClosed(); } + final long startPosition = source.position(); + long count = source.size() - source.position(); final long remainingContentLength = remainingContentLength(); + if (count > remainingContentLength) { + count = remainingContentLength; + } if (listener == null) { if (buffer != null && buffer.position() != 0) { writeBufferBlocking(false); @@ -564,12 +569,7 @@ public void transferFrom(FileChannel source) throws IOException { if (channel == null) { channel = servletRequestContext.getExchange().getResponseChannel(); } - long position = source.position(); - long count = source.size() - position; - if (count > remainingContentLength) { - count = remainingContentLength; - } - Channels.transferBlocking(channel, source, position, count); + Channels.transferBlocking(channel, source, startPosition, count); updateWritten(count); } else { setFlags(FLAG_WRITE_STARTED); @@ -577,25 +577,23 @@ public void transferFrom(FileChannel source) throws IOException { long pos = 0; try { - long size = Math.min (source.size(), remainingContentLength); - pos = source.position(); + long end = pos + count; + pos = startPosition; - while (size - pos > 0) { - long ret = channel.transferFrom(pendingFile, pos, size - pos); + while (end - pos > 0) { + long ret = channel.transferFrom(pendingFile, pos, end - pos); if (ret <= 0) { clearFlags(FLAG_READY); pendingFile = source; - source.position(pos); channel.resumeWrites(); return; } pos += ret; } } finally { - updateWrittenAsync(pos - source.position()); + updateWrittenAsync(pos - startPosition); } } - }