Offset stream provides the possibility to simulate a longer stream with a virtual empty space at the beginning with the size of offset.
Inheritance: StreamWrapper
        public void LengthTest() {
            // static length test
            using (MemoryStream memstream = new MemoryStream(this.content))
            using (OffsetStream offsetstream = new OffsetStream(memstream, this.offset)) {
                Assert.AreEqual(this.offset + this.content.Length, offsetstream.Length);
            }

            // dynamic length test
            using (MemoryStream memstream = new MemoryStream())
            using (OffsetStream offsetstream = new OffsetStream(memstream, this.offset)) {
                Assert.AreEqual(0, memstream.Length);
                Assert.AreEqual(this.offset, offsetstream.Length);
                offsetstream.SetLength(200);
                Assert.AreEqual(200, offsetstream.Length);
                Assert.AreEqual(200 - this.offset, memstream.Length);
                Assert.Throws<ArgumentOutOfRangeException>(() => offsetstream.SetLength(50));
                Assert.AreEqual(200, offsetstream.Length);
                Assert.AreEqual(200 - this.offset, memstream.Length);
            }
        }
 public void ResumeTest() {
     byte[] inputContent = new byte[100];
     long offset = 100;
     using (var stream = new MemoryStream(inputContent)) 
     using (var offsetstream = new OffsetStream(stream, offset)) {
         using (var progress = new ProgressStream(offsetstream)) {
             progress.PropertyChanged += delegate(object sender, System.ComponentModel.PropertyChangedEventArgs e) {
                 var p = sender as ProgressStream;
                 if (e.PropertyName == Utils.NameOf(() => p.Position)) {
                     this.position = (long)p.Position;
                     this.percent = p.Percent.GetValueOrDefault();
                 }
             };
             progress.Seek(0, SeekOrigin.Begin);
             Assert.AreEqual(offset, this.position);
             Assert.AreEqual(50, this.percent);
             progress.Seek(10, SeekOrigin.Current);
             Assert.AreEqual(offset + 10, this.position);
             progress.Seek(0, SeekOrigin.End);
             Assert.AreEqual(100, this.percent);
             Assert.AreEqual(offset + inputContent.Length, this.position);
             progress.Seek(0, SeekOrigin.Begin);
             progress.WriteByte(0);
             Assert.AreEqual(offset + 1, this.position);
             Assert.AreEqual(50.5, this.percent);
             progress.WriteByte(0);
             Assert.AreEqual(offset + 2, this.position);
             Assert.AreEqual(51, this.percent);
             progress.Write(new byte[10], 0, 10);
             Assert.AreEqual(56, this.percent);
         }
     }
 }
示例#3
0
        /// <summary>
        ///  Uploads the file.
        ///  Resumes an upload if the given localFileStream.Position is larger than zero.
        /// </summary>
        /// <returns>
        ///  The new CMIS document.
        /// </returns>
        /// <param name='remoteDocument'>
        ///  Remote document where the local content should be uploaded to.
        /// </param>
        /// <param name='localFileStream'>
        ///  Local file stream.
        /// </param>
        /// <param name='transmission'>
        ///  Transmission status where the uploader should report its uploading status.
        /// </param>
        /// <param name='hashAlg'>
        ///  Hash alg which should be used to calculate a checksum over the uploaded content.
        /// </param>
        /// <param name='overwrite'>
        ///  If true, the local content will overwrite the existing content.
        /// </param>
        /// <param name="update">Is called on every new chunk, if not <c>null</c>.</param>
        /// <exception cref="CmisSync.Lib.Tasks.UploadFailedException">
        /// Contains the last successful remote document state. This is needed for continue a failed upload.
        /// </exception>
        public override IDocument UploadFile(
            IDocument remoteDocument,
            Stream localFileStream,
            Transmission transmission,
            HashAlgorithm hashAlg,
            bool overwrite = true,
            UpdateChecksum update = null)
        {
            IDocument result = remoteDocument;
            for (long offset = localFileStream.Position; offset < localFileStream.Length; offset += this.ChunkSize) {
                bool isFirstChunk = offset == 0;
                bool isLastChunk = (offset + this.ChunkSize) >= localFileStream.Length;
                using (var hashstream = new NonClosingHashStream(localFileStream, hashAlg, CryptoStreamMode.Read))
                using (var chunkstream = new ChunkedStream(hashstream, this.ChunkSize))
                using (var offsetstream = new OffsetStream(chunkstream, offset))
                using (var transmissionStream = transmission.CreateStream(offsetstream)) {
                    transmission.Length = localFileStream.Length;
                    transmission.Position = offset;
                    chunkstream.ChunkPosition = offset;

                    ContentStream contentStream = new ContentStream();
                    contentStream.FileName = remoteDocument.Name;
                    contentStream.MimeType = Cmis.MimeType.GetMIMEType(remoteDocument.Name);
                    if (isLastChunk) {
                        contentStream.Length = localFileStream.Length - offset;
                    } else {
                        contentStream.Length = this.ChunkSize;
                    }

                    contentStream.Stream = transmissionStream;
                    try {
                        if (isFirstChunk && result.ContentStreamId != null && overwrite) {
                            result.DeleteContentStream(true);
                        }

                        result.AppendContentStream(contentStream, isLastChunk, true);
                        HashAlgorithmReuse reuse = hashAlg as HashAlgorithmReuse;
                        if (reuse != null && update != null) {
                            using (HashAlgorithm hash = (HashAlgorithm)reuse.Clone()) {
                                hash.TransformFinalBlock(new byte[0], 0, 0);
                                update(hash.Hash, result.ContentStreamLength.GetValueOrDefault());
                            }
                        }
                    } catch (Exception e) {
                        if (e is FileTransmission.AbortException) {
                            throw;
                        }

                        if (e.InnerException is FileTransmission.AbortException) {
                            throw e.InnerException;
                        }

                        throw new UploadFailedException(e, result);
                    }
                }
            }

            hashAlg.TransformFinalBlock(new byte[0], 0, 0);
            return result;
        }
        private int DownloadNextChunk(IDocument remoteDocument, long offset, long remainingBytes, Transmission transmission, Stream outputstream, HashAlgorithm hashAlg) {
            lock(this.disposeLock) {
                if (this.disposed) {
                    transmission.Status = TransmissionStatus.ABORTED;
                    throw new ObjectDisposedException(transmission.Path);
                }

                IContentStream contentStream = remoteDocument.GetContentStream(remoteDocument.ContentStreamId, offset, remainingBytes);
                transmission.Length = remoteDocument.ContentStreamLength;
                transmission.Position = offset;

                using (var remoteStream = contentStream.Stream)
                using (var forwardstream = new ForwardReadingStream(remoteStream))
                using (var offsetstream = new OffsetStream(forwardstream, offset))
                using (var progress = transmission.CreateStream(offsetstream)) {
                    byte[] buffer = new byte[8 * 1024];
                    int result = 0;
                    int len;
                    while ((len = progress.Read(buffer, 0, buffer.Length)) > 0) {
                        outputstream.Write(buffer, 0, len);
                        hashAlg.TransformBlock(buffer, 0, len, buffer, 0);
                        result += len;
                        outputstream.Flush();
                    }

                    return result;
                }
            }
        }
        public void SeekTest() {
            using (MemoryStream memstream = new MemoryStream(this.content))
            using (OffsetStream offsetstream = new OffsetStream(memstream, this.offset)) {
                Assert.True(offsetstream.CanSeek);
                Assert.AreEqual(memstream.CanSeek, offsetstream.CanSeek);
                Assert.AreEqual(memstream.Position + this.offset, offsetstream.Position);
                long pos = offsetstream.Seek(10, SeekOrigin.Begin);
                Assert.AreEqual(110, pos);
                Assert.AreEqual(10, memstream.Position);
                pos = offsetstream.Seek(0, SeekOrigin.End);
                Assert.AreEqual(offsetstream.Length, pos);
                Assert.AreEqual(memstream.Length, memstream.Position);
                pos = offsetstream.Seek(0, SeekOrigin.Current);
                Assert.AreEqual(offsetstream.Length, pos);
                Assert.AreEqual(memstream.Length, memstream.Position);
                offsetstream.Seek(10, SeekOrigin.Begin);
                pos = offsetstream.Seek(10, SeekOrigin.Current);
                Assert.AreEqual(this.offset + 20, pos);
                Assert.AreEqual(20, memstream.Position);

                // negative seek
                pos = offsetstream.Seek(-10, SeekOrigin.Current);
                Assert.AreEqual(this.offset + 10, pos);
                Assert.AreEqual(10, memstream.Position);
                pos = offsetstream.Seek(-10, SeekOrigin.Current);
                Assert.AreEqual(this.offset, pos);
                Assert.AreEqual(0, memstream.Position);

                // seek into illegal areas
                Assert.Throws<IOException>(() => { pos = offsetstream.Seek(-10, SeekOrigin.Current); });
                Assert.AreEqual(this.offset, pos);
                Assert.AreEqual(0, memstream.Position);
            }

            // Using an unseekable stream should return CanSeek = false
            var mockstream = new Mock<Stream>();
            mockstream.SetupGet(s => s.CanSeek).Returns(false);
            using (OffsetStream offsetstream = new OffsetStream(mockstream.Object)) {
                Assert.False(offsetstream.CanSeek);
            }
        }
 public void ConstructorWithOffset() {
     using (var stream = new OffsetStream(new Mock<Stream>().Object, 10)) {
         Assert.AreEqual(10, stream.Offset);
     }
 }
        public void WriteTest() {
            // Write one block
            using (MemoryStream memstream = new MemoryStream())
            using (OffsetStream offsetstream = new OffsetStream(memstream, this.offset)) {
                Assert.AreEqual(0, memstream.Position);
                Assert.AreEqual(this.offset, offsetstream.Position);
                offsetstream.Write(this.content, 0, this.content.Length);
                Assert.AreEqual(this.content.Length + this.offset, offsetstream.Position);
                Assert.AreEqual(this.content, memstream.ToArray());
            }

            // Write single bytes
            using (MemoryStream memstream = new MemoryStream())
            using (OffsetStream offsetstream = new OffsetStream(memstream, this.offset)) {
                Assert.AreEqual(0, memstream.Position);
                Assert.AreEqual(this.offset, offsetstream.Position);
                foreach (byte b in this.content) {
                    offsetstream.WriteByte(b);
                }

                Assert.AreEqual(this.content.Length + this.offset, offsetstream.Position);
                Assert.AreEqual(this.content, memstream.ToArray());
            }
        }
 public void ReadTest() {
     // Read block
     byte[] buffer = new byte[this.contentLength];
     using (MemoryStream memstream = new MemoryStream(this.content))
     using (OffsetStream offsetstream = new OffsetStream(memstream, this.offset)) {
         Assert.AreEqual(0, memstream.Position);
         Assert.AreEqual(this.offset, offsetstream.Position);
         int len = offsetstream.Read(buffer, 0, buffer.Length);
         Assert.AreEqual(this.contentLength, len);
         Assert.AreEqual(this.contentLength + this.offset, offsetstream.Position);
         Assert.AreEqual(this.content, buffer);
         len = offsetstream.Read(buffer, 0, buffer.Length);
         Assert.AreEqual(0, len);
     }
 }