Exemplo n.º 1
0
        /// <summary>
        /// Handles the creation of an actual data block based on the underlying resource.
        /// </summary>
        /// <param name="transfer">The processed transfer.</param>
        /// <param name="blockNumber">The number of the downloaded block.</param>
        /// <param name="previouslyTransferredBlock">If this data block was already transferred, this parameter
        /// contains the information about the block. Can be used in order to ensure proper retransmission in case
        /// of variable block sizes.</param>
        /// <returns>A data block which exposes the data as a resource-friendly stream
        /// (<see cref="BufferedDataBlock.Data"/>).</returns>
        protected override StreamedDataBlock CreateStreamedDataBlockImpl(LocalDownloadTransfer transfer, long blockNumber, DataBlockInfo previouslyTransferredBlock)
        {
            //this func creates the returned DataBlock by reading a chunk of data
            //from the underlying stream.
            Func <long, StreamedDataBlock> func = position =>
            {
                DownloadToken token = transfer.Token;

                //check if we can use the max block size
                long streamLength = transfer.Stream.Length;
                int  blockLength  = (int)Math.Min(token.DownloadBlockSize,
                                                  streamLength - position);
                if (blockLength < 0)
                {
                    blockLength = 0;
                }

                ChunkStream stream = new ChunkStream(transfer.Stream, blockLength,
                                                     position, false);


                return(new StreamedDataBlock
                {
                    TransferTokenId = transfer.TransferId,
                    BlockNumber = blockNumber,
                    BlockLength = blockLength,
                    Offset = position,
                    Data = stream,
                    IsLastBlock = blockNumber == token.TotalBlockCount - 1
                });
            };

            return(PrepareAndRunBlockReading(transfer, blockNumber, func));
        }
Exemplo n.º 2
0
        /// <summary>
        /// 删除录播任务
        /// </summary>
        public void DeleteRecording(DownloadToken token)
        {
            var key = token.LinkedSchedule.Key;

            RecordScheduleManager.DeleteSchedule(token.LinkedSchedule);
            _TaskList.Remove(key);
            TaskList.Remove(token);
        }
 public PartialViewResult ConfigExchange()
 {
     ViewData["ConfigLink"] = new DownloadToken
     {
         ContentType       = "application/json",
         DownloadName      = options.DownloadName,
         DownloadReason    = options.DownloadReason,
         FileDownload      = true,
         FileIdentifier    = options.FileIdentifier,
         HandlerModuleName = options.UploadModuleName
     }.CompressToken();
     return(PartialView(options));
 }
        private void BuildDownloadToken(TutorialStream model, TutorialStreamViewModel vm)
        {
            var token = new DownloadToken
            {
                FileDownload      = true,
                ContentType       = vm.ContentType,
                DownloadName      = $"Video{model.TutorialStreamId}.{model.ContentType.Substring(model.ContentType.IndexOf("/") + 1)}",
                DownloadReason    = "DownloadTutorial",
                FileIdentifier    = $"##VID#{vm.VideoTutorialId}#{vm.TutorialStreamId}",
                HandlerModuleName = VideoFileHandler
            }.CompressToken();

            vm.DownloadToken = token;
        }
Exemplo n.º 5
0
        /// <summary>
        /// Creates a token for the currently processed resource.
        /// </summary>
        /// <param name="submittedResourceFilePath">The identifier (file path)
        /// for the requested resource, as submitted by the requesting party.</param>
        /// <param name="fileItem">Represents the requested file.</param>
        /// <param name="clientMaxBlockSize">The maximum size of a downloadable block, as requested by
        /// the client. It is up to the implementing method to correct this value (e.g. in order
        /// to comply to the <see cref="TransferHandlerBase{TFile,TToken,TTransfer}.MaxBlockSize"/>
        /// of the service itself.</param>
        /// <param name="includeFileHash">Whether a file hash for the
        /// requested resource should be calculated and assigned to the
        /// <see cref="DownloadToken.Md5FileHash"/> property of the returned
        /// <see cref="DownloadToken"/>.</param>
        /// <returns>A token for the request.</returns>
        protected override DownloadToken CreateDownloadToken(string submittedResourceFilePath, ZipFileItem fileItem, int?clientMaxBlockSize, bool includeFileHash)
        {
            var    fileInfo   = fileItem.ResourceInfo;
            string transferId = Guid.NewGuid().ToString();

            //try to comply to the requested block size, if specified. Otherwise
            //apply the default
            int blockSize = clientMaxBlockSize.HasValue
                        ? Math.Min(clientMaxBlockSize.Value, MaxBlockSize ?? int.MaxValue)
                        : Configuration.FileSystemConfiguration.DefaultDownloadBlockSize;


            var token = new DownloadToken
            {
                TransferId         = transferId,
                ResourceIdentifier = submittedResourceFilePath,
                CreationTime       = SystemTime.Now(),
                ContentType        = fileInfo.ContentType,
                ResourceName       = fileInfo.Name,
                ResourceLength     = fileInfo.Length,
                DownloadBlockSize  = blockSize
            };

            TimeSpan?expiration = Configuration.FileSystemConfiguration.DownloadTokenExpirationTime;

            if (expiration.HasValue)
            {
                token.ExpirationTime = SystemTime.Now().Add(expiration.Value);
            }

            //calculate number of blocks
            long blockCount = token.ResourceLength / blockSize;

            if ((token.ResourceLength % token.DownloadBlockSize) != 0)
            {
                blockCount++;
            }
            token.TotalBlockCount = blockCount;

            if (includeFileHash)
            {
                using (var reader = fileItem.Node.FileEntry.OpenReader())
                {
                    token.Md5FileHash = reader.CalculateMd5Hash();
                }
            }

            return(token);
        }
        public void Init()
        {
            store = new InMemoryTransferStore <DownloadTransfer <FileItem> >();

            transfers = new List <DownloadTransfer <FileItem> >();
            for (int i = 0; i < 10; i++)
            {
                FileItem item = new FileItem {
                    LocalFile = new FileInfo(i.ToString())
                };
                var token = new DownloadToken {
                    TransferId = i.ToString()
                };
                transfers.Add(new DownloadTransfer <FileItem>(token, item));
            }
        }
Exemplo n.º 7
0
        /// <summary>
        /// Handles the creation of an actual data block based on the underlying resource.
        /// </summary>
        /// <param name="transfer">The processed transfer.</param>
        /// <param name="blockNumber">The number of the downloaded block.</param>
        /// <param name="previouslyTransferredBlock">If this data block was already transferred, this parameter
        /// contains the information about the block. Can be used in order to ensure proper retransmission in case
        /// of variable block sizes.</param>
        /// <returns>A data block which contains the data as an in-memory buffer
        /// (<see cref="BufferedDataBlock.Data"/>).</returns>
        protected override BufferedDataBlock CreateBufferedDataBlockImpl(LocalDownloadTransfer transfer, long blockNumber, DataBlockInfo previouslyTransferredBlock)
        {
            //this func creates the returned DataBlock by reading a chunk of data
            //from the underlying stream.
            Func <long, BufferedDataBlock> func = position =>
            {
                DownloadToken token = transfer.Token;

                //read data
                byte[] data = new byte[token.DownloadBlockSize];
                int    read = transfer.Stream.Read(data, 0, data.Length);
                if (read < token.DownloadBlockSize)
                {
                    Array.Resize(ref data, read);
                }

                return(new BufferedDataBlock
                {
                    TransferTokenId = transfer.TransferId,
                    BlockNumber = blockNumber,
                    BlockLength = data.Length,
                    Offset = position,
                    Data = data,
                    IsLastBlock = blockNumber == token.TotalBlockCount - 1
                });
            };

            var dataBlock = PrepareAndRunBlockReading(transfer, blockNumber, func);

            if (dataBlock.IsLastBlock)
            {
                //assume the last block will be processed successfully and
                //already close the stream (don't wait for the transfer to be
                //closed by client). This would still reopen the stream if
                //necessary
                CloseStream(transfer);
            }

            return(dataBlock);
        }
Exemplo n.º 8
0
        /// <summary>
        /// 在前台创建录播任务
        /// </summary>
        public DownloadToken StartRecording(Channel channel, SourceRecord source, DateTimeOffset startTime, TimeSpan span)
        {
            // 注册相关信息
            string identifer = channel.UniqueId + source.StationName + startTime.ToString("yyMMddHHmmss");
            var    schedule  = RecordScheduleManager.CreateSchedule(identifer, source.Source.AbsoluteUri, startTime, span);
            var    token     = new DownloadToken()
            {
                Channel        = channel,
                Source         = source.StationName,
                LinkedSchedule = schedule
            };

            _TaskList.Add(schedule.Key, token);
            TaskList.Add(token);

            // 开始任务
            var diff = startTime.Subtract(DateTimeOffset.Now);

            if (diff > TimeSpan.FromMinutes(15))
            {
                RecordScheduleManager.LaunchSchedule(schedule);
                new MessageDialog("由于系统原因,后台定时任务的精度为15分钟,为保证录下您指定的时间段,将提前15分钟开始录制,请预留足够的硬盘空间", "提示").ShowAsync();
            }
            else
            {
                if (diff <= TimeSpan.Zero)
                {
                    RecordScheduleManager.LaunchRecording(schedule);
                }
                else
                {
                    // TODO: 由于ThreadPoolTimer会受到程序进入后台的影响,因此可以考虑在这里改用后台任务强行等待
                    new MessageDialog("由于系统不支持15分钟内的后台定时任务,请您在录制开始前将本程序保持开启并避免最小化!开始后即可关闭程序", "提示").ShowAsync();
                    ThreadPoolTimer.CreateTimer((timer) => RecordScheduleManager.LaunchRecording(schedule), diff);
                }
            }

            return(token);
        }
Exemplo n.º 9
0
        public void Refreshing_Token_After_Multiple_Read_Should_Still_Indicate_The_Last_Block_Number()
        {
            for (int i = 0; i < 10; i++)
            {
                DownloadService.ReadBlock(Token.TransferId, i);
            }

            DataBlockInfo lastBlock = null;

            //redownload a few of these blocks
            for (int i = 0; i < 10; i++)
            {
                if (i % 2 == 0)
                {
                    lastBlock = DownloadService.ReadBlock(Token.TransferId, i);
                }
            }

            DownloadToken copy = DownloadService.RenewToken(Token, false);

            Assert.AreEqual(lastBlock.BlockNumber, copy.LastTransmittedBlockInfo.BlockNumber);
        }
Exemplo n.º 10
0
        /// <summary>
        /// Creates a transfer object for a given requested resource.
        /// </summary>
        /// <param name="submittedResourceFilePath">The resource identifier as submitted.</param>
        /// <param name="fileItem">Represents the requested file resource.</param>
        /// <param name="token">The token that is being issued for the transfer.</param>
        /// <param name="claims">The access rights for the resource.</param>
        /// <param name="lockGuard">File locks, if necessary. Can be a null reference
        /// if no locking takes place.</param>
        /// <param name="expirationJob">A scheduled job that invokes the
        /// <see cref="TransferHandlerBase{TFile,TToken,TTransfer}.OnTransferExpiration"/>"/>
        /// method once the transfer expires. May be null if the token does not expire.</param>
        /// <returns>A transfer object which encapsulates the information required to perform
        /// the transfer.</returns>
        protected override LocalDownloadTransfer CreateTransfer(string submittedResourceFilePath, FileItem fileItem,
                                                                DownloadToken token, FileClaims claims,
                                                                ResourceLockGuard lockGuard,
                                                                Job <DownloadToken> expirationJob)
        {
            var transfer = new LocalDownloadTransfer(token, fileItem)
            {
                Status = TransferStatus.Starting
            };

            if (expirationJob != null)
            {
                transfer.ExpirationNotificationJob = expirationJob;
            }
            if (lockGuard != null)
            {
                transfer.ResourceLock = lockGuard;
            }
            transfer.Owner = Config.Provider.Security.GetIdentity();

            return(transfer);
        }
Exemplo n.º 11
0
        private RecordService()
        {
            // 如果没有恢复TaskList话则手动恢复
            if (_TaskList.Count == 0)
            {
                Utils.Async.InvokeAndWait(async() => await _TaskList.Restore());
            }

            // 同步前后台的列表
            foreach (var schedule in RecordScheduleManager.GetSchedules())
            {
                var key = schedule.Key;
                if (_TaskList.ContainsKey(key))
                {
                    _TaskList[key].LinkedSchedule = schedule;
                }
                else
                {
                    var token = new DownloadToken()
                    {
                        Channel        = Channel.GetChannel("unknown", "未知频道"),
                        Source         = "未知来源",
                        LinkedSchedule = schedule
                    };
                    _TaskList.Add(schedule.Key, token);
                }
            }
            foreach (var item in _TaskList.ToList()) // 利用ToList方法创建副本
            {
                if (item.Value.LinkedSchedule == null)
                {
                    _TaskList.Remove(item.Key);
                }
            }

            // 初始化前台列表并添加事件监听
            TaskList = new ObservableCollection <DownloadToken>(_TaskList.Values);
        }
Exemplo n.º 12
0
 /// <summary>
 /// 终止后台录播任务
 /// </summary>
 public void TerminateRecording(DownloadToken token) =>
 RecordScheduleManager.TerminateSchedule(token.LinkedSchedule);
Exemplo n.º 13
0
 /// <summary>
 /// Initializes a new instance of the <see cref="T:System.Object"/> class.
 /// </summary>
 public LocalDownloadTransfer(DownloadToken token, FileItem fileItem) : base(token, fileItem)
 {
 }
Exemplo n.º 14
0
 /// <summary>
 /// Initializes a new instance of the <see cref="T:System.Object"/> class.
 /// </summary>
 public DownloadTransfer(DownloadToken token, TFile fileItem) : base(token, fileItem)
 {
 }
Exemplo n.º 15
0
 /// <summary>
 /// Initializes a new instance of the <see cref="T:System.Object"/> class.
 /// </summary>
 public ZipDownloadTransfer(DownloadToken token, ZipFileItem fileItem) : base(token, fileItem)
 {
 }