public override FileTransferResponsed Handle(ContextRequest request, FileWriteHandleContext context)
        {
            FileTransferResponsed responsed = new FileTransferResponsed(request.FileRequest);
            var r = request.FileRequest;

            if (r.IsSendingOver)//在文件写入完成时,检查文件MD5
            {
                if (request.ProgressDic.ContainsKey(r.FileMd5))
                {
                    request.ProgressDic[r.FileMd5].StateMsg = "校验中";
                    //request.ProgressDic.Remove(r.FileMd5);
                }
#if DEBUG
                Console.WriteLine("Normal file send finished,prepare to check fileMD5");
#endif
                context.State = new StateFileExist();//检查文件长度是否相等或超过。PS:可能存在陷入无限死循环的隐患,调试时注意
                return(context.Request(request));
            }

            try
            {
                using (var fs = File.OpenWrite(request.WorkingPath))
                {
                    //在文件未传输完成时,持续写入文件
                    using (BinaryWriter bs = new BinaryWriter(fs))
                    {
                        //Console.WriteLine($"seekoffset{r.SeekOffset},index={r.BlockIndex},length={r.BlockData.Length}");
                        bs.Seek((int)r.SeekOffset, SeekOrigin.Begin);
                        bs.Write(r.BlockData);
                        responsed.RemoteStreamPosition = fs.Position;
                    }
                }
                var progress = request.ProgressDic[r.FileMd5];
                progress.MaxValue      = r.BlockCount;
                progress.ProgressValue = r.BlockIndex;
                progress.Title         = r.FileName;
                progress.StateMsg      = "传输中";

                try
                {
                    request?.ReceiveProgressHandler?.OnRecieving(r.FileMd5);
                    //PubSubEvents.Singleton.Publish(new FileReceiveProgressChangedEvent() { ProgressMsg = request.ProgressDic[r.FileMd5] });
                }
                catch
                {
                    // ignored
                }
            }
            catch (Exception e)
            {
#if DEBUG
                Console.WriteLine(e);
#endif
                responsed.IsError = true;
                responsed.ErrMsg  = e.Message;
            }
            return(responsed);
        }
        public override FileTransferResponsed Handle(ContextRequest request, FileWriteHandleContext context)
        {
            var r = request.FileRequest;

            if (!request.ProgressDic.ContainsKey(r.FileMd5))
            {
                var progress = new ProgressMessage();
                request.ProgressDic.Add(r.FileMd5, progress);

                try
                {
                    request?.ReceiveProgressHandler?.OnReceiveStart(r.FileMd5, progress);
                }
                catch
                {
                    // ignored
                }
            }

            //若文件存在,则进入文件存在状态
            if (File.Exists(request.WorkingPath))
            {
                context.State = new StateFileExist();
                return(context.Request(request));
            }

            FileTransferResponsed responsed = new FileTransferResponsed(request.FileRequest);

            try
            {
                //创建文件并写入第一块数据
                using (var fs = new FileStream(request.WorkingPath, FileMode.Create, FileAccess.Write))
                {
                    var data = request.FileRequest.BlockData;
                    fs.Write(data, 0, data.Length);
                    responsed.RemoteStreamPosition = fs.Position;
                }
                //TODO : 将Block的信息存起来,最好把每个Block的MD5值存起来,方便使用本地对比,而不是连接远程对比。或从远程下载BLock信息,再在本地读取,PS:内存也可。
            }
            catch (Exception e)
            {
#if DEBUG
                Console.WriteLine(e);
#endif
                responsed.IsError = true;
                responsed.ErrMsg  = e.Message;
            }
            context.State = new StateFileNormalTransfer();
            return(responsed);
        }
        public override FileTransferResponsed Handle(ContextRequest request, FileWriteHandleContext context)
        {
            var r = request.FileRequest;

            //Console.WriteLine("StateFileLengthEqual");
            var fs = request.WorkingStream;
            //bug : filestream appeared that has been closed

            string md5      = fs.CanRead ? Md5.GetMd5WithFileStream(fs, fs.Position) : Md5.GetMd5WithFilePath(request.WorkingPath);
            var    progress = request.ProgressDic[r.FileMd5];
            FileTransferResponsed responsed = new FileTransferResponsed(request.FileRequest)
            {
                IsSendingOver      = true,
                FileMd5CheckResult = md5 == request.FileRequest.FileMd5
                                     //文件长度相等,则视为已传输完毕
            };

            if (responsed.FileMd5CheckResult)
            {
                fs.Close();
                var path = FileNameTools.GetDownloadedFullPath(request.WorkingPath);
                File.Move(request.WorkingPath, path);//modify filename

                progress.ProgressValue = progress.MaxValue;
                progress.StateMsg      = "校验成功!";
                try
                {
                    request?.ReceiveProgressHandler?.OnReceiveEnd(r.FileMd5, true);
                    //PubSubEvents.Singleton.Publish(new FileReceiveProgressCompleteEvent() { IsChecked = true,FileName = r.FileName });
                }
                catch
                {
                    // ignored
                }
            }
            else
            {
                request?.ReceiveProgressHandler?.OnReceiveEnd(r.FileMd5, false);
                progress.StateMsg = "校验失败!正在重新检查,请耐心等待。";
                //PubSubEvents.Singleton.GetEvent<FileReceiveProgressCompleteEvent>().Publish(new FileReceiveProgressCompleteEvent() { IsChecked = false, FileName = r.FileName });

                context.State = new StateFileNormalTransfer();//等待单个Block文件写入
            }
            return(responsed);
        }
예제 #4
0
        public override FileTransferResponsed Handle(ContextRequest request, FileWriteHandleContext context)
        {
            //将文件削减至规定长度再重新进行MD5校验
            var fs = request.WorkingStream;

            if (fs.CanWrite)
            {
                fs.SetLength(request.FileRequest.FileSize);
                fs.Flush();
                context.State = new StateFileLengthEqual();
            }
            else
            {
                throw new NotImplementedException("FileStream不允许写入");
            }

            return(context.Request(request));
        }
예제 #5
0
        public override FileTransferResponsed Handle(ContextRequest request, FileWriteHandleContext context)
        {
            long fsLength;
            FileTransferResponsed responsed;

            using (request.WorkingStream = File.Open(request.WorkingPath, FileMode.Open, FileAccess.ReadWrite))
            {
                fsLength = request.WorkingStream.Length;
                if (fsLength > request.FileRequest.FileSize)
                {
                    context.State = new StateFileLengthOutRange();
                    responsed     = context.Request(request);
                }
                else if (fsLength == request.FileRequest.FileSize)
                {
                    context.State = new StateFileLengthEqual();
                    responsed     = context.Request(request);
                }
                else//文件实际长度既不大于也不等于远程端文件长度时
                {
                    context.State = new StateFileNormalTransfer();//若检查全部通过,则下一个状态是普通传输文件状态

                    if (fsLength >= request.FileRequest.EachBlockSize)//返回文件在倒数第2个Block时的offset,让远程端从该处发送对应Block数据,然后进入普通文件传输状态
                    {
                        var  fRequest = request.FileRequest;
                        long position = ((fsLength / fRequest.EachBlockSize) - 1) * fRequest.EachBlockSize;

                        responsed = new FileTransferResponsed(request.FileRequest);
                        responsed.RemoteStreamPosition = position;
                    }
                    else//若文件长度小于区块长度,则直接按普通方式写入文件,此时远程SeekOffset应为0
                    {
                        request.WorkingStream.Close();//防止正常写入文件时触发文件被占用异常
                        responsed = context.Request(request);
                    }
                }
            }
            return(responsed);//保证FileStream被Using释放后才return
        }
예제 #6
0
 public abstract FileTransferResponsed Handle(ContextRequest request, FileWriteHandleContext context);