diff --git a/handler/src/main/java/io/netty/handler/stream/ChunkedNioFile.java b/handler/src/main/java/io/netty/handler/stream/ChunkedNioFile.java index be0696955dd..ec3e4115f15 100644 --- a/handler/src/main/java/io/netty/handler/stream/ChunkedNioFile.java +++ b/handler/src/main/java/io/netty/handler/stream/ChunkedNioFile.java @@ -25,6 +25,7 @@ import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; +import java.nio.channels.ClosedChannelException; import java.nio.channels.FileChannel; /** @@ -100,9 +101,8 @@ public ChunkedNioFile(FileChannel in, long offset, long length, int chunkSize) t "chunkSize: " + chunkSize + " (expected: a positive integer)"); } - - if (offset != 0) { - in.position(offset); + if (!in.isOpen()) { + throw new ClosedChannelException(); } this.in = in; this.chunkSize = chunkSize; @@ -160,7 +160,7 @@ public ByteBuf readChunk(ByteBufAllocator allocator) throws Exception { try { int readBytes = 0; for (;;) { - int localReadBytes = buffer.writeBytes(in, chunkSize - readBytes); + int localReadBytes = buffer.writeBytes(in, offset + readBytes, chunkSize - readBytes); if (localReadBytes < 0) { break; } diff --git a/handler/src/test/java/io/netty/handler/stream/ChunkedWriteHandlerTest.java b/handler/src/test/java/io/netty/handler/stream/ChunkedWriteHandlerTest.java index 59dbf7ebba2..010d98851a1 100644 --- a/handler/src/test/java/io/netty/handler/stream/ChunkedWriteHandlerTest.java +++ b/handler/src/test/java/io/netty/handler/stream/ChunkedWriteHandlerTest.java @@ -26,13 +26,17 @@ import io.netty.channel.embedded.EmbeddedChannel; import io.netty.util.CharsetUtil; import io.netty.util.ReferenceCountUtil; +import org.junit.Assert; import org.junit.Test; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; +import java.io.RandomAccessFile; import java.nio.channels.Channels; +import java.nio.channels.ClosedChannelException; +import java.nio.channels.FileChannel; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; @@ -102,6 +106,41 @@ public void testChunkedNioFile() throws IOException { check(new ChunkedNioFile(TMP), new ChunkedNioFile(TMP), new ChunkedNioFile(TMP)); } + @Test + public void testChunkedNioFileLeftPositionUnchanged() throws IOException { + FileChannel in = null; + final long expectedPosition = 10; + try { + in = new RandomAccessFile(TMP, "r").getChannel(); + in.position(expectedPosition); + check(new ChunkedNioFile(in) { + @Override + public void close() throws Exception { + //no op + } + }); + Assert.assertTrue(in.isOpen()); + Assert.assertEquals(expectedPosition, in.position()); + } finally { + if (in != null) { + in.close(); + } + } + } + + @Test(expected = ClosedChannelException.class) + public void testChunkedNioFileFailOnClosedFileChannel() throws IOException { + final FileChannel in = new RandomAccessFile(TMP, "r").getChannel(); + in.close(); + check(new ChunkedNioFile(in) { + @Override + public void close() throws Exception { + //no op + } + }); + Assert.fail(); + } + @Test public void testUnchunkedData() throws IOException { check(Unpooled.wrappedBuffer(BYTES));