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; }