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); }
/// <summary> /// 检查是否处于断点续传状态 /// </summary> /// <param name="responsed"></param> /// <param name="request"></param> /// <param name="info"></param> /// <param name="fsPosition"></param> /// <param name="positionOffset"></param> /// <param name="sendBlockSize"></param> private void OfflineReSendCheck(FileTransferResponsed responsed, FileTransferRequest request, FileBlockInfo info, long fsPosition, ref long positionOffset, ref int sendBlockSize) { if (responsed.RemoteStreamPosition == fsPosition) { request.BlockIndex++; } else { int rBlockIndex = 0; long rPosition = 0; ClacBlockIndex(info, responsed.RemoteStreamPosition, out rBlockIndex, out rPosition); request.BlockIndex = rBlockIndex; positionOffset = rPosition; } if (info.BlockSize > info.FileLength - positionOffset) { sendBlockSize = (int)(info.FileLength - positionOffset); } }
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 }
/// <summary> /// 根据反馈,重发文件 /// </summary> /// <param name="path"></param> /// <param name="fileBlockInfo"></param> /// <param name="request"></param> /// <param name="checkResponsed"></param> private bool ReSendFile(string path, FileBlockInfo fileBlockInfo, FileTransferRequest request, FileTransferResponsed checkResponsed) { return(ReSendFile(path, _fileStreamDic[path], fileBlockInfo, request, checkResponsed)); }
/// <summary> /// 根据反馈结果,重发文件 /// </summary> /// <param name="path"></param> /// <param name="fs"></param> /// <param name="fileBlockInfo"></param> /// <param name="request"></param> /// <param name="checkResponsed"></param> public bool ReSendFile(string path, FileStream fs, FileBlockInfo fileBlockInfo, FileTransferRequest request, FileTransferResponsed checkResponsed) { int resendCountOut = 0; while (!checkResponsed.FileMd5CheckResult && resendCountOut < 3)//最多重发三次 { #if DEBUG Console.WriteLine("ReSending File, count " + resendCountOut); #endif //MD5检查失败重发 var blockMsgList = ClacFileEachBlockMd5(fileBlockInfo, fs); if (blockMsgList.Count != fileBlockInfo.BlockCount) { throw new Exception("校准MD5时,Block数量计算错误!"); } int size = request.EachBlockSize; request.IsSendingOver = false; for (int i = 0; i < blockMsgList.Count; i++) { var blockCheck = _sendAdapter.UpdateFileBlockMessage(blockMsgList[i]); if (blockCheck.IsError) { if (i == blockMsgList.Count - 1) { size = request.LastBlockSize; } request.BlockIndex = i; request.SeekOffset = i * fileBlockInfo.BlockSize; request.BlockData = ReadFileBytes(path, request.SeekOffset, size); _sendAdapter.UpdateFileData(request); } } request.IsSendingOver = true; checkResponsed = _sendAdapter.UpdateFileData(request); resendCountOut++; } return(checkResponsed.FileMd5CheckResult); }
public void HandleResponsed(FileTransferResponsed responsed) { //throw new NotImplementedException(); }