0.先上章效果图吧;
1.目录结构:
2.上传客户端类库介绍:
ITransferEngine:
public interface ITransferEngine { /// <summary> /// 该事件接口暴露了所有正在上传的文件(夹)的实时状态。 /// </summary> IFileUploadingEvents FileUploadingEvents { get; } void BeginUpLoad(string fileName, string saveName); void BeginUpLoad(string fileName, string saveName, ref string fileId, ref string AddId); } public interface IFileUploadingEvents { event BTransferEventHandler<EventArgs> FileExist; event TransferEventHandler<EventArgs> TransferComplete; event TransferEventHandler<TransferErrorEventArgs> TransferError; event TransferEventHandler<TransferStepEventArgs> TransferStep; }
TransferEngine:
internal class TransferEngine : ITransferEngine { private FileUploadingEvents _FileUploadingEvents; public IFileUploadingEvents FileUploadingEvents { get { return _FileUploadingEvents; } } public TransferEngine() { _FileUploadingEvents = new FileUploadingEvents(); } public void BeginUpLoad(string fileName, string saveName) { EndPoint endpoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 2020); UpLoadEngine engine = new UpLoadEngine(_FileUploadingEvents); engine.Init(endpoint, fileName, Path.GetFileName(fileName)); engine.BeginUpLoad(); } public void BeginUpLoad(string fileName, string saveName, ref string fileId, ref string AddId) { EndPoint endpoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 2020); UpLoadEngine engine = new UpLoadEngine(_FileUploadingEvents); engine.Init(endpoint, fileName, saveName); engine.BeginUpLoad(ref fileId, ref AddId); } }
上传的相关事件:
public delegate void TransferEventHandler<TEventArgs>(TEventArgs e); public delegate bool BTransferEventHandler<TEventArgs>(TEventArgs e); public class TransferStepEventArgs : EventArgs { public TransferStepEventArgs(long _TotalLen, long _TransferLen, int _CurrentPacket) { this.TotalLen = _TotalLen; this.TransferLen = _TransferLen; this.CurrentPacket = _CurrentPacket; } public int CurrentPacket { get; set; } public long TotalLen { get; set; } public long TransferLen { get; set; } } public class TransferErrorEventArgs : EventArgs { public TransferErrorEventArgs(System.Exception exception) { this.Exception = exception; } public System.Exception Exception { get; private set; } }
internal class FileUploadingEvents : IFileUploadingEvents { internal BTransferEventHandler<EventArgs> OnFileExist; internal TransferEventHandler<EventArgs> OnTransferComplete; internal TransferEventHandler<TransferErrorEventArgs> OnTransferError; internal TransferEventHandler<TransferStepEventArgs> OnTransferStep; public event BTransferEventHandler<EventArgs> FileExist { add { OnFileExist = (BTransferEventHandler<EventArgs>)System.Delegate.Combine(OnFileExist, value); } remove { OnFileExist = (BTransferEventHandler<EventArgs>)System.Delegate.Remove(OnFileExist, value); } } public event TransferEventHandler<EventArgs> TransferComplete { add { OnTransferComplete = (TransferEventHandler<EventArgs>)System.Delegate.Combine(OnTransferComplete, value); } remove { OnTransferComplete = (TransferEventHandler<EventArgs>)System.Delegate.Remove(OnTransferComplete, value); } } public event TransferEventHandler<TransferErrorEventArgs> TransferError { add { OnTransferError = (TransferEventHandler<TransferErrorEventArgs>)System.Delegate.Combine(OnTransferError, value); } remove { OnTransferError = (TransferEventHandler<TransferErrorEventArgs>)System.Delegate.Remove(OnTransferError, value); } } public event TransferEventHandler<TransferStepEventArgs> TransferStep { add { OnTransferStep = (TransferEventHandler<TransferStepEventArgs>)System.Delegate.Combine(OnTransferStep, value); } remove { OnTransferStep = (TransferEventHandler<TransferStepEventArgs>)System.Delegate.Remove(OnTransferStep, value); } } }
UpLoadEngine:
internal class UpLoadEngine : IDisposable { FileUploadingEvents FileUploadingEvents; protected IClientCommandReader<TransferCommandInfo> CommandReader { get; private set; } private string _fileName; public string _saveName; private Dictionary<string, ICommand<UpLoadEngine, TransferCommandInfo>> m_CommandDict = new Dictionary<string, ICommand<UpLoadEngine, TransferCommandInfo>>(StringComparer.OrdinalIgnoreCase); private FileStream m_fileStream; private int PacketSize = 1024 * 30; private byte[] readBuffer; private long TransferedLength = 0L; internal int TransferStatus = 0; //0:初始化状态,1:CheckExist,3,OnUpLoad,开始上传,4,OnDoData,数据传输中,5,数据传输完成,6,已结束的标志 private long TransferTotalLength = 0L; internal TcpClientSession Client; internal AutoResetEvent m_OpenedEvent = new AutoResetEvent(false); internal AutoResetEvent m_EndEvent = new AutoResetEvent(false); public UpLoadEngine(FileUploadingEvents _FileUploadingEvents) { this.FileUploadingEvents = _FileUploadingEvents; } public void BeginUpLoad() { try { if (this.TransferStatus != 0) { throw new Exception("状态错误"); } this.Client.Connect(); if (!this.m_OpenedEvent.WaitOne(5000)) { throw new Exception("连接失败"); } this.SendMessage(UpLoadOP.CheckExist, this._saveName); } catch (Exception exception) { this.OnTransferError(new TransferErrorEventArgs(exception)); } } internal void BeginUpLoad(ref string fileId, ref string AddId) { BeginUpLoad(); fileId = string.Empty; AddId = string.Empty; } private void client_Closed(object sender, EventArgs e) { this.TransferStatus = 6; } private void client_Connected(object sender, EventArgs e) { this.m_OpenedEvent.Set(); } private void client_DataReceived(object sender, DataEventArgs e) { this.m_OnDataReceived(e.Data, e.Offset, e.Length); } private void client_Error(object sender, SuperSocket.ClientEngine.ErrorEventArgs e) { } public void Dispose() { this._fileName = string.Empty; this._saveName = string.Empty; if (this.m_fileStream != null) { this.m_fileStream.Close(); this.m_fileStream = null; } TcpClientSession client = this.Client; if (client != null) { client.Error -= new EventHandler<SuperSocket.ClientEngine.ErrorEventArgs>(this.client_Error); client.DataReceived -= new EventHandler<DataEventArgs>(this.client_DataReceived); client.Connected -= new EventHandler(this.client_Connected); client.Closed -= new EventHandler(this.client_Closed); if (client.IsConnected) { client.Close(); } this.Client = null; } //this.TransferStatus = 0; this.TransferedLength = 0L; this.TransferTotalLength = 0L; this.readBuffer = null; this.CommandReader = null; this.m_CommandDict.Clear(); this.m_OpenedEvent.Reset(); this.m_EndEvent.Reset(); } internal void DoData() { this.TransferStatus = 4; while (this.TransferedLength < this.TransferTotalLength) { if (this.TransferStatus == 6) { if (this.Client != null && !this.Client.IsConnected) { this.OnTransferError(new TransferErrorEventArgs(new Exception("服务端关闭"))); return; } else { this.DoEnd(); return; } } int length = this.m_fileStream.Read(this.readBuffer, 0, this.PacketSize); this.SendData(UpLoadOP.DoData, this.readBuffer, 0, length); this.TransferedLength += length; this.OnTransferStep(this.TransferTotalLength, this.TransferedLength, length); } this.TransferStatus = 5; this.SendData(UpLoadOP.DoEnd, new byte[] { 1 }, 0, 1); DoEnd(); } internal void DoEnd() { this.TransferStatus = 6; this.Dispose(); if (this.FileUploadingEvents.OnTransferComplete != null) { this.FileUploadingEvents.OnTransferComplete(new EventArgs()); } } //客户端自己触发结束事件 //internal void OnDoEnd() //{ // DoEnd(); //} internal void DoUpLoad() { this.m_fileStream = new FileStream(this._fileName, FileMode.Open, FileAccess.Read); this.TransferTotalLength = this.m_fileStream.Length; UpLoadInfo t = new UpLoadInfo(this._fileName, this.m_fileStream.Length, _SaveName: this._saveName); byte[] data = SerializeHelp.Serialize<UpLoadInfo>(t); this.SendData(UpLoadOP.DoUpLoad, data, 0, data.Length); } private void ExecuteCommand(TransferCommandInfo commandInfo) { ICommand<UpLoadEngine, TransferCommandInfo> command; if (this.m_CommandDict.TryGetValue(commandInfo.Key, out command)) { command.ExecuteCommand(this, commandInfo); } } public void Init(EndPoint endpoint, string fileName, string saveName) { string str = ConfigurationManager.AppSettings["PacketSize"]; if (!string.IsNullOrWhiteSpace(str)) { this.PacketSize = Convert.ToInt32(str); } this.readBuffer = new byte[this.PacketSize]; this._fileName = fileName; this._saveName = saveName; UpLoadCommandBase[] baseArray = new UpLoadCommandBase[] { new CheckExist(), new TransferClientLib.UpLoad.Command.DoData(), new TransferClientLib.UpLoad.Command.DoEnd() }; foreach (UpLoadCommandBase base2 in baseArray) { this.m_CommandDict.Add(base2.Name, base2); } TcpClientSession session = new AsyncTcpSession(endpoint); session.Error += new EventHandler<SuperSocket.ClientEngine.ErrorEventArgs>(this.client_Error); session.DataReceived += new EventHandler<DataEventArgs>(this.client_DataReceived); session.Connected += new EventHandler(this.client_Connected); session.Closed += new EventHandler(this.client_Closed); this.Client = session; this.CommandReader = new UpLoadReader(this); } private void m_OnDataReceived(byte[] data, int offset, int length) { while (true) { if (this.CommandReader == null) return; int num; TransferCommandInfo commandInfo = this.CommandReader.GetCommandInfo(data, offset, length, out num); if (this.CommandReader.NextCommandReader != null) { this.CommandReader = this.CommandReader.NextCommandReader; } if (commandInfo != null) { this.ExecuteCommand(commandInfo); } if (num <= 0) { return; } offset = (offset + length) - num; length = num; } } internal bool OnFileExist() { if (this.FileUploadingEvents.OnFileExist != null) { this.FileUploadingEvents.OnFileExist(new EventArgs()); } this.OnTransferError(new TransferErrorEventArgs(new Exception("存在相同文件"))); return false; } internal void OnTransferError(TransferErrorEventArgs e) { if (this.FileUploadingEvents.OnTransferError != null) { this.FileUploadingEvents.OnTransferError(e); } this.Dispose(); } internal void OnTransferStep(long _TotalLen, long _TransferLen, int _CurrentPacket) { if (this.FileUploadingEvents.OnTransferStep != null) { this.FileUploadingEvents.OnTransferStep(new TransferStepEventArgs(_TotalLen, _TransferLen, _CurrentPacket)); } } internal void SendData(UpLoadOP opCode, byte[] data, int offset, int length) { byte[] senddata = new byte[length + 5]; senddata[0] = 0; senddata[1] = (byte)((int)opCode / 256); senddata[2] = (byte)((int)opCode % 256); senddata[3] = (byte)(length / 256); senddata[4] = (byte)(length % 256); Buffer.BlockCopy(data, offset, senddata, 5, length); this.Client.Send(senddata, 0, senddata.Length); } internal void SendMessage(UpLoadOP opCode, string msg) { byte[] bytes = Encoding.UTF8.GetBytes(msg); this.SendData(opCode, bytes, 0, bytes.Length); } }
3.服务端
UpLoadEngine,应该命名叫UpLoadServerEngine,跟客户端有个区分
public class UpLoadEngine : IDisposable { private AutoResetEvent m_EndEvent = new AutoResetEvent(false); private FileStream m_fileStream; private int TransferStatus = 0; //0:初始化状态,1:CheckFile,3,OnUpLoad,开始上传,4,OnDoData,数据接受中,5,数据接受完成,6,已结束的标志 public long TransferedLength = 0L; private TransferServerLib.TransferSession TransferSession; public TransferCommon.UpLoadInfo UpLoadInfo; Thread thread; public delegate void TransferStepEventHandler(TransferStepEventArgs e); public event TransferStepEventHandler TransferStep; public delegate void TransferCompleteEventHandler(EventArgs e); public event TransferCompleteEventHandler TransferComplete; public delegate void StartTransferEventHandler(StartTransferEventArgs e); public event StartTransferEventHandler StartTransfer; public UpLoadEngine(TransferServerLib.TransferSession _TransferSession) { this.TransferStatus = 0; this.TransferSession = _TransferSession; } public void Dispose() { if (this.m_fileStream != null) { this.m_fileStream.Close(); this.m_fileStream = null; } if (this.TransferSession != null) { this.TransferSession.Close(); this.TransferSession = null; } if (thread != null) { if (thread.IsAlive) thread.Abort(); thread = null; } this.UpLoadInfo = null; this.TransferedLength = 0L; } internal void OnCheckFile(UpLoadOP opCode, bool IsFileExist) { this.TransferStatus = 1; string s = IsFileExist ? "1" : "0"; byte[] bytes = Encoding.UTF8.GetBytes(s); this.SendData(opCode, bytes, 0, bytes.Length); } public void OnDoData(byte[] data, int offset, int count) { this.TransferStatus = 4; this.m_fileStream.Write(data, offset, count); this.TransferedLength += count; this.OnTransferStep(this.UpLoadInfo.TransferLength, TransferedLength, count); if (this.TransferedLength >= this.UpLoadInfo.TransferLength) { this.TransferStatus = 5; thread = new Thread(new ThreadStart(() => { if (!this.m_EndEvent.WaitOne(5000)) { if (this.TransferStatus < 6) { DoEnd(); } } })); thread.IsBackground = true; thread.Start(); } } internal void OnTransferStep(long _TotalLen, long _TransferLen, int _CurrentPacket) { if (this.TransferStep != null) { this.TransferStep(new TransferStepEventArgs(_TotalLen, _TransferLen, _CurrentPacket)); } } public void DoEnd() { this.TransferSession.Close(); this.Dispose(); this.TransferStatus = 6; if (TransferComplete != null) TransferComplete(new EventArgs()); } public void OnDoEnd() { DoEnd(); } internal void OnUpLoad(TransferCommon.UpLoadInfo uploadInfo) { this.TransferStatus = 3; this.UpLoadInfo = uploadInfo; if (StartTransfer != null) { StartTransfer(new StartTransferEventArgs(uploadInfo)); } string fullPath = Path.GetFullPath(uploadInfo.SaveName); string dirPath = Path.GetDirectoryName(fullPath); if (!Directory.Exists(dirPath)) { Directory.CreateDirectory(dirPath); } this.m_fileStream = new FileStream(fullPath, FileMode.OpenOrCreate, FileAccess.Write); this.m_fileStream.SetLength(uploadInfo.FileSize); this.SendData(UpLoadOP.DoData, new byte[] { 1 }, 0, 1); } internal void SendData(UpLoadOP opCode, byte[] data, int offset, int length) { byte[] dst = new byte[length + 4]; dst[0] = (byte)((int)opCode / 256); dst[1] = (byte)((int)opCode % 256); dst[2] = (byte)(data.Length / 256); dst[3] = (byte)(data.Length % 256); Buffer.BlockCopy(data, offset, dst, 4, length); this.TransferSession.Send(dst, 0, dst.Length); } }
程序还没写好,还要更新,请多多指点
git os china ,为啥不用github,因为速度没有oschina快。https://git.oschina.net/dishiyicijinqiu/TransferSolution/tree/develop