diff --git a/src/cs-S3Zip/S3MultipartDownloadStream.cs b/src/cs-S3Zip/S3MultipartDownloadStream.cs
index 2b134032f1ffd8a88bad8dcc65cc227b5e2171e9..7aad41f1a1b7a66bc749e641b1b0d14a7db639c9 100644
--- a/src/cs-S3Zip/S3MultipartDownloadStream.cs
+++ b/src/cs-S3Zip/S3MultipartDownloadStream.cs
@@ -1,5 +1,6 @@
 using Amazon.S3;
 using Amazon.S3.Model;
+using System;
 using System.IO;
 
 namespace coscine.cs_S3Zip
@@ -7,7 +8,6 @@ namespace coscine.cs_S3Zip
     public class S3MultipartDownloadStream : Stream
     {
         private readonly Stream _internalStream;
-        private int _part;
         private readonly long _length;
         private long _position;
 
@@ -23,14 +23,13 @@ namespace coscine.cs_S3Zip
 
         public override long Length => _length;
 
-        public override long Position { get => _position + _internalStream.Position; set => throw new System.NotImplementedException(); }
+        public override long Position { get => _position + _internalStream.Position; set => Seek(value - Position, SeekOrigin.Current); }
 
         public S3MultipartDownloadStream(string key, S3MultipartStreamConfiguration s3MultipartStreamConfiguration, Stream internalStream)
         {
             S3MultipartStreamConfiguration = s3MultipartStreamConfiguration;
 
             _internalStream = internalStream;
-            _part = 0;
             _position = 0;
 
             Key = key;
@@ -46,7 +45,7 @@ namespace coscine.cs_S3Zip
                 _length = meta.Headers.ContentLength;
             }
 
-            DownloadCurrentPart();
+            DownloadRange(new ByteRange(0, Position + S3MultipartStreamConfiguration.ChunckSize - 1));
         }
 
         public S3MultipartDownloadStream(string key, S3MultipartStreamConfiguration s3MultipartStreamConfiguration) : this(key, s3MultipartStreamConfiguration, new MemoryStream(s3MultipartStreamConfiguration.ChunckSize))
@@ -76,21 +75,6 @@ namespace coscine.cs_S3Zip
             _internalStream.Position = 0;
         }
 
-        private void DownloadCurrentPart()
-        {
-            if (Position < Length)
-            {
-                DownloadPart(_part);
-                _part++;
-            }
-        }
-
-        private void DownloadPart(int part)
-        {
-            _position += _internalStream.Position;
-            DownloadRange(new ByteRange(part * S3MultipartStreamConfiguration.ChunckSize, (part + 1) * S3MultipartStreamConfiguration.ChunckSize - 1));
-        }
-
         public override void Flush()
         {
             _internalStream.Flush();
@@ -111,7 +95,9 @@ namespace coscine.cs_S3Zip
                 {
                     int toBeRead = (int)(_internalStream.Length - _internalStream.Position);
                     read += _internalStream.Read(buffer, offset + read, toBeRead);
-                    DownloadCurrentPart();
+                    var oldPosition = _internalStream.Position;
+                    DownloadRange(new ByteRange(Position, Position + S3MultipartStreamConfiguration.ChunckSize - 1));
+                    _position += oldPosition;
                 }
             }
 
@@ -156,28 +142,39 @@ namespace coscine.cs_S3Zip
 
         public override long Seek(long offset, SeekOrigin origin)
         {
+            //var a = _internalStream.Seek(offset, origin);
+            //return a;
+            
+            var position = 0L;
+
             switch (origin)
             {
                 case SeekOrigin.Begin:
-                    DownloadRange(CalculateByteRange(offset));
-                    _position = offset;
+                    position = offset;
                     break;
                 case SeekOrigin.Current:
-                    if (Position + offset > _position + _internalStream.Length || Position + offset < _position)
-                    {
-                        DownloadRange(CalculateByteRange(Position + offset));
-                        _position = Position + offset;
-                    } else
-                    {
-                        _internalStream.Position += offset;
-                    }
+                    position = Position + offset;
                     break;
                 case SeekOrigin.End:
-                    DownloadRange(CalculateByteRange(_length - 1 + offset));
-                    _position = _length - 1 + offset;
+                    position = Length + offset;
                     break;
             }
 
+            var realOffset = position - Position;
+
+            // is the position still buffered?
+            if ((realOffset >= 0 && _internalStream.Position + realOffset < _internalStream.Length) 
+                || (realOffset < 0 && _internalStream.Position + realOffset >= 0))
+            {
+                _internalStream.Position += realOffset;
+            } else
+            {
+                var range = CalculateByteRange(position);
+                DownloadRange(range);
+                _internalStream.Position = position - range.Start;
+                _position = range.Start;
+            }
+
             return Position;
         }