Пример #1
0
        /// <summary>
        /// Reads a data block's stream and writes it to a given <paramref name="targetStream"/>.
        /// </summary>
        /// <param name="dataBlock">The data block that provides a chunk of data that should
        /// be written to the <paramref name="targetStream"/>.</param>
        /// <param name="targetStream">The target stream that receives the block's
        /// <see cref="StreamedDataBlock.Data"/>.</param>
        /// <param name="maxStreamSize">The maximum number of bytes that can be written to the destination
        /// stream. If the read stream exceeds this limit, a <see cref="DataBlockException"/> is thrown.</param>
        /// <exception cref="DataBlockException">If the data block's stream length exceeds the
        /// <paramref name="maxStreamSize"/> threshhold.</exception>
        public static void WriteTo(this StreamedDataBlock dataBlock, Stream targetStream, long maxStreamSize)
        {
            //use default byte sizes
            byte[] buffer = new byte[32768];

            long totalBytesRead = 0;

            while (true)
            {
                int bytesRead = dataBlock.Data.Read(buffer, 0, buffer.Length);
                totalBytesRead += bytesRead;

                if (totalBytesRead > maxStreamSize)
                {
                    string msg = "The length of the stream of data block number [{0}] for transfer [{1}] exceeds the size limit of [{2}] bytes.";
                    msg = String.Format(msg, dataBlock.BlockNumber, dataBlock.TransferTokenId, maxStreamSize);
                    throw new DataBlockException(msg);
                }

                if (bytesRead > 0)
                {
                    targetStream.Write(buffer, 0, bytesRead);
                }
                else
                {
                    targetStream.Flush();
                    break;
                }
            }
        }
Пример #2
0
        /// <summary>
        /// Splits a stream into chunks using a <see cref="ChunkStream"/>, and wraps them into
        /// <see cref="StreamedDataBlock"/> instances that can be sent to an <see cref="IUploadTransferHandler"/>.
        /// This overload allows to resume a transfer and start with a given offset.
        /// <br/>This extension method also takes care of implicitly completing the upload by setting the
        /// <see cref="IDataBlock.IsLastBlock"/> property of the last block to true.
        /// </summary>
        /// <param name="sourceStream">The source stream that provides the data to be uploaded.</param>
        /// <param name="token">An upload token that defines the resource.</param>
        /// <param name="resourceLength">The total length of the submitted stream.</param>
        /// <param name="blockSize">The block size to be used. All blocks (except the last one) will have
        /// this size.</param>
        /// <param name="initialBlockNumber">The initial block number to be used.</param>
        /// <param name="offset">The offset of the first written block (0 to start at the beginning of the stream).</param>
        /// <param name="writerAction">An action that is being invoked for every created <see cref="StreamedDataBlock"/>
        /// instance.</param>
        /// <remarks>The position within the stream is only set according to the submitted
        /// <paramref name="offset"/> if the underlying <paramref name="sourceStream"/> supports seeking as indicated by
        /// its <see cref="Stream.CanSeek"/> property.</remarks>
        public static void WriteTo(this Stream sourceStream, UploadToken token, long resourceLength, int blockSize, long initialBlockNumber, long offset, Action <StreamedDataBlock> writerAction)
        {
            long remaining   = resourceLength;
            long position    = offset;
            long blockNumber = initialBlockNumber;

            while (remaining > 0)
            {
                //decorate the stream with a chunk stream that limits access to a block of data
                int         chunkSize = (int)Math.Min(remaining, blockSize);
                ChunkStream cs        = new ChunkStream(sourceStream, chunkSize, position, sourceStream.CanSeek);

                StreamedDataBlock dataBlock = new StreamedDataBlock
                {
                    TransferTokenId = token.TransferId,
                    BlockLength     = chunkSize,
                    BlockNumber     = blockNumber,
                    Data            = cs,
                    Offset          = position
                };

                //update position within stream and remaining bytes
                position  += chunkSize;
                remaining -= chunkSize;
                blockNumber++;

                if (remaining == 0)
                {
                    //implicitly complete the transfer by marking the last block
                    dataBlock.IsLastBlock = true;
                }

                writerAction(dataBlock);
            }
        }
Пример #3
0
        public void StartDownload()
        {
            if (Token == null)
            {
                Token = TransferService.RequestDownloadToken(ResourceId, false);
            }

            while (true)
            {
                IDataBlockInfo blockInfo;
                string         transferId = Token.TransferId;

                long nextBlock = 0;
                if (Token.LastTransmittedBlockInfo != null)
                {
                    nextBlock = Token.LastTransmittedBlockInfo.BlockNumber + 1;
                }

                if (UseStreamingTransfer)
                {
                    StreamedDataBlock block = TransferService.ReadBlockStreamed(transferId, nextBlock);
                    block.Data.WriteTo(OutputStream);
                    blockInfo = block;
                }
                else
                {
                    BufferedDataBlock block = TransferService.ReadBlock(transferId, nextBlock);
                    OutputStream.Write(block.Data, 0, block.Data.Length);
                    blockInfo = block;
                }

                //update the token, get independent file info without data or stream
                Token.LastTransmittedBlockInfo  = DataBlockInfo.FromDataBlock(blockInfo);
                Token.LastBlockTransmissionTime = SystemTime.Now();

                if (blockInfo.IsLastBlock)
                {
                    //we're done - update token data
                    Token.CompletionTime = Token.LastBlockTransmissionTime;
                    TransferService.CompleteTransfer(transferId);
                    Token.Status = TransferStatus.Completed;

                    break;
                }
            }
        }
    protected override void InitInternal()
    {
      base.InitInternal();
      InitToken();

      byte[] buffer = new byte[10000];
      Array.Copy(SourceFileContents, buffer, 10000);

      BufferedBlock = new BufferedDataBlock
                        {
                          TransferTokenId = Token.TransferId,
                          BlockLength = 10000,
                          Data = buffer
                        };

      StreamedBlock = new StreamedDataBlock
                        {
                          TransferTokenId = Token.TransferId,
                          BlockLength = 10000,
                          Data = new ChunkStream(new MemoryStream(SourceFileContents), 10000, 0, false)
                        };
    }
    private void WriteBlock(string transferId, long blockNumber, Stream input)
    {
      //get meta information from headers
      VfsHttpHeaders headerNames = VfsHttpHeaders.Default;
      HttpHeaderDictionary headers = Request.Headers;

      var blockLength = Convert.ToInt32(headers[headerNames.BlockLength]);
      var isLastBlock = headers.ContainsKey(headerNames.IsLastBlock) ? Convert.ToBoolean(headers[headerNames.IsLastBlock]) : false;
      var offset = Convert.ToInt64(headers[headerNames.BlockOffset]);

      StreamedDataBlock block = new StreamedDataBlock
                                  {
                                    TransferTokenId = transferId,
                                    BlockNumber = blockNumber,
                                    IsLastBlock = isLastBlock,
                                    BlockLength = blockLength,
                                    Offset = offset,
                                    Data = new NonSeekableStream(input)
                                  };

      FileSystem.UploadTransfers.WriteBlockStreamed(block);
    }
    protected override void InitInternal()
    {
      base.InitInternal();
      InitToken();

      //read first 10000 bytes
      byte[] buffer = GetBuffer(10000);


      BufferedBlock = new BufferedDataBlock
                        {
                          TransferTokenId = Token.TransferId,
                          BlockLength = 10000,
                          Data = buffer
                        };

      StreamedBlock = new StreamedDataBlock
                        {
                          TransferTokenId = Token.TransferId,
                          BlockLength = 10000,
                          Data = new ChunkStream(new MemoryStream(buffer), 10000, 0, false)
                        };
    }
Пример #7
0
 /// <summary>
 /// 
 /// </summary>
 public void WriteBlockStreamed(StreamedDataBlock block)
 {
   throw new NotImplementedException();
 }
    /// <summary>
    /// Splits a stream into chunks using a <see cref="ChunkStream"/>, and wraps them into
    /// <see cref="StreamedDataBlock"/> instances that can be sent to an <see cref="IUploadTransferHandler"/>.
    /// This overload allows to resume a transfer and start with a given offset.
    /// <br/>This extension method also takes care of implicitly completing the upload by setting the
    /// <see cref="IDataBlock.IsLastBlock"/> property of the last block to true.
    /// </summary>
    /// <param name="sourceStream">The source stream that provides the data to be uploaded.</param>
    /// <param name="token">An upload token that defines the resource.</param>
    /// <param name="resourceLength">The total length of the submitted stream.</param>
    /// <param name="blockSize">The block size to be used. All blocks (except the last one) will have
    /// this size.</param>
    /// <param name="initialBlockNumber">The initial block number to be used.</param>
    /// <param name="offset">The offset of the first written block (0 to start at the beginning of the stream).</param>
    /// <param name="writerAction">An action that is being invoked for every created <see cref="StreamedDataBlock"/>
    /// instance.</param>
    /// <remarks>The position within the stream is only set according to the submitted
    /// <paramref name="offset"/> if the underlying <paramref name="sourceStream"/> supports seeking as indicated by
    /// its <see cref="Stream.CanSeek"/> property.</remarks>
    public static void WriteTo(this Stream sourceStream, UploadToken token, long resourceLength, int blockSize, long initialBlockNumber, long offset, Action<StreamedDataBlock> writerAction)
    {
      long remaining = resourceLength;
      long position = offset;
      long blockNumber = initialBlockNumber;

      while(remaining > 0)
      {
        //decorate the stream with a chunk stream that limits access to a block of data
        int chunkSize = (int)Math.Min(remaining, blockSize);
        ChunkStream cs = new ChunkStream(sourceStream, chunkSize, position, sourceStream.CanSeek);

        StreamedDataBlock dataBlock = new StreamedDataBlock
                                 {
                                   TransferTokenId = token.TransferId,
                                   BlockLength = chunkSize,
                                   BlockNumber = blockNumber,
                                   Data = cs,
                                   Offset = position
                                 };

        //update position within stream and remaining bytes
        position += chunkSize;
        remaining -= chunkSize;
        blockNumber++;

        if(remaining == 0)
        {
          //implicitly complete the transfer by marking the last block
          dataBlock.IsLastBlock = true;
        }

        writerAction(dataBlock);
      }
    }
Пример #9
0
 /// <summary>
 /// Reads a data block's stream and writes it to a given <paramref name="targetStream"/>.
 /// </summary>
 /// <param name="dataBlock">The data block that provides a chunk of data that should
 /// be written to the <paramref name="targetStream"/>.</param>
 /// <param name="targetStream">The target stream that receives the block's
 /// <see cref="StreamedDataBlock.Data"/>.</param>
 public static void WriteTo(this StreamedDataBlock dataBlock, Stream targetStream)
 {
     targetStream.Position = dataBlock.Offset;
     dataBlock.Data.WriteTo(targetStream);
 }
 /// <summary>
 /// Uploads a given data block that provides a chunk of data for an uploaded file as a stream.
 /// </summary>
 /// <param name="block">The block to be written.</param>
 /// <exception cref="DataBlockException">If the data block's contents cannot be stored,
 /// either because it's an invalid number, or because only sequential downloads
 /// are possible, and the block does not refer to the current download
 /// position.
 /// </exception>
 /// <exception cref="TransferStatusException">If the transfer has already expired.</exception>
 void IFSDataUploadService.WriteDataBlockStreamed(StreamedDataBlock block)
 {
   throw new NotImplementedException();
 }