• [转载]一个C#文件传输模块,支持断点续传


    转自:http://www.cnblogs.com/takamachi660/archive/2009/08/06/1540022.html

    最近做一个程序需要传送文件,在网上找了好久也没找到好用的方案,于是自己写了一个,与大家分享,希望大家帮忙改进,拍砖欢迎~
    文件采取分块发送,每块单独校验,能够保证文件的完整性.同时还提供磁盘缓存功能.
    经过实际测试,通过局域网(有线和WiFi)传送一个5G左右的文件取得成功.
    最大缺点是CPU占用率过高,测试中发送端(939AMD3000+)达到40%,接收端(双核T9600、939AMD3200+)分别为15%和35%左右.
    性能确实还有待改进....
    贴出部分代码,其他的放附件里:

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Net.Sockets;
    using System.Text;
    using System.Threading;
    namespace Takamachi660.FileTransmissionSolution
    {//Version 0.6
        #region CRC32算法
        /// <summary>
        /// CRC32快速检测算法
        /// 本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/ZZJ_4Ever/archive/2009/03/31/4038551.aspx
        /// 有稍作修改
        /// </summary>
        public static class CRC32
        {
            static UInt32[] crcTable = {   
             0x0, 0x77073096, 0xee0e612c, 0x990951ba, 0x76dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,   
             0xedb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x9b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,   
             0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,   
             0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,   
             0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,   
             0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,   
             0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,   
             0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,   
             0x76dc4190, 0x1db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x6b6b51f, 0x9fbfe4a5, 0xe8b8d433,   
             0x7807c9a2, 0xf00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x86d3d2d, 0x91646c97, 0xe6635c01,   
             0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,   
             0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,   
             0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,   
             0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,   
             0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,   
             0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,   
             0xedb88320, 0x9abfb3b6, 0x3b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x4db2615, 0x73dc1683,   
             0xe3630b12, 0x94643b84, 0xd6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0xa00ae27, 0x7d079eb1,   
             0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,   
             0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,   
             0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,   
             0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,   
             0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,   
             0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,   
             0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x26d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x5005713,   
             0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0xcb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0xbdbdf21,   
             0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,   
             0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,   
             0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,   
             0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,   
             0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,   
             0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,                          
                                       };
            public static int GetCRC32(byte[] bytes)
            {
                int iCount = bytes.Length;
                UInt32 crc = 0xFFFFFFFF;
                for (int i = 0; i < iCount; i++)
                {
                    crc = ((crc >> 8) & 0x00FFFFFF) ^ crcTable[(crc ^ bytes[i]) & 0xFF];
                }
                UInt32 temp = crc ^ 0xFFFFFFFF;
                int t = (int)temp;
                return (t);
            }
        }
        #endregion
    
        #region 一些常量和扩展方法
        /// <summary>
        /// 一些常量和扩展方法
        /// </summary>
        public static class Consts
        {
            /// <summary>
            /// 文件区块数据标头
            /// </summary>
            public const byte FileBlockHeader = 0;
            /// <summary>
            /// 字符串信息标头
            /// </summary>
            public const byte StringHeader = 1;
            /// <summary>
            /// 分块大小1MB
            /// </summary>
            public const int BlockSize = 1048576;
            /// <summary>
            /// 网络上传送的数据包最大大小
            /// </summary>
            public const int NetBlockMaxSize = BlockSize + 9;
            /// <summary>
            /// 默认磁盘缓存大小(单位:区块数)
            /// </summary>
            public const int DefaultIOBufferSize = 8;
            /// <summary>
            /// 空格
            /// </summary>
            public const string Space = " ";
            /// <summary>
            /// 空格替代符
            /// </summary>
            public const string SpaceReplacement = @"<SPACE>";
            /// <summary>
            /// 获取校验值
            /// </summary>
            /// <param name="bytes">输入数据</param>
            /// <returns>输出的校验值</returns>
            public static byte[] GetHash(this byte[] bytes)
            {
                return BitConverter.GetBytes(CRC32.GetCRC32(bytes));
            }
            /// <summary>
            /// 比较两二进制数据内容是否完全相同(用于校验值的比较)
            /// </summary>
            /// <param name="THIS">数据一</param>
            /// <param name="obj">数据二</param>
            public static bool BytesEqual(this byte[] THIS, byte[] obj)
            {
                if (THIS.Length != obj.Length)
                    return false;
                for (int index = 0; index < obj.Length; index++)
                {
                    if (THIS[index] != obj[index])
                        return false;
                }
                return true;
            }
            /// <summary>
            /// 将指令字符串转化为二进制数据并添加标头
            /// </summary>
            public static byte[] ToBytes(this string str_input)
            {
                byte[] strdata = Encoding.UTF8.GetBytes(str_input);
                byte[] output = new byte[1 + strdata.Length];
                output[0] = StringHeader;
                System.Array.Copy(strdata, 0, output, 1, strdata.Length);
                return output;
            }
            /// <summary>
            /// 将二进制数据转化为指令字符串
            /// </summary>
            public static string ToFTString(this byte[] bytes_input)
            {
                if (bytes_input[0] != StringHeader)
                    throw new FormatException("Bad Header!");
                return Encoding.UTF8.GetString(bytes_input, 1, bytes_input.Length - 1).TrimEnd('\0');
            }
            /// <summary>
            /// 替换可能会对命令解析造成干扰的字符
            /// </summary>
            public static string DoReplace(this string str_input)
            {
                return str_input.Replace(Space, SpaceReplacement);
            }
            /// <summary>
            /// 还原被替换的字符
            /// </summary>
            public static string DeReplace(this string str_input)
            {
                return str_input.Replace(SpaceReplacement, Space);
            }
        }
        #endregion
    
        #region 一些委托
        public delegate void BlockFinishedEventHandler(object sender, BlockFinishedEventArgs e);
        public delegate void CommandReceivedEventHandler(object sender, CommandReceivedEventArgs e);
        public delegate void FileTransmissionErrorOccurEventHandler(object sender,FileTransmissionErrorOccurEventArgs e);
        public delegate void Delegate_SendBlocks(int Start, int End);
        public delegate void Delegate_Void_Bool(bool logic);
        public delegate int Delegate_Int_Int(int value);
        #endregion
    
        #region 文件区块类
        public class FileBlockException : Exception
        {
            public enum ErrorCode
            {
                BadHeader,
                BadIndex,
                IllegalFileBlockSize,
                ChecksumError,
            }
            public ErrorCode Code { get; set; }
            public FileBlockException(string message, ErrorCode ErrorCode)
                : base(message)
            {
                Code = ErrorCode;
            }
        }
        /// <summary>
        /// 文件区块类
        /// </summary>
        public class FileBlock : IComparable<FileBlock>
        {
            /// <summary>
            /// 与该区块关联的传输对象
            /// </summary>
            internal FileTransmission _Task;
            /// <summary>
            /// 与该区块关联的FileStream
            /// </summary>
            internal FileStream _FileStream;
            /// <summary>
            /// 文件数据
            /// </summary>
            internal byte[] _Data;
            /// <summary>
            /// 数据长度
            /// </summary>
            internal int _DataLength;
            /// <summary>
            /// 数据的Hash值
            /// </summary>
            internal byte[] _DataHash;
            /// <summary>
            /// 获取或设置该区块的序号(该区块在文件中的位置)
            /// </summary>
            public int Index { get; set; }
            /// <summary>
            /// 获取该区块的数据长度
            /// </summary>
            public int DataLength { get { return _DataLength; } }
            /// <summary>
            /// 获取该数据块的校验值
            /// </summary>
            public byte[] DataHash { get { return _DataHash; } }
            /// <summary>
            /// 构造函数
            /// 用于从文件读入区块
            /// </summary>
            /// <param name="fStream">输入的文件流</param>
            /// <param name="BlockIndex">分块位置</param>
            /// <param name="ReadOnCreated">是否立即从文件读取数据</param>
            public FileBlock(FileTransmission TransmissionTask, int BlockIndex, bool ReadOnCreated)
            {
                _Task = TransmissionTask;
                _FileStream = _Task.FileStream;
                Index = BlockIndex;
                if (ReadOnCreated)
                    this.Read(true);
            }
            /// <summary>
            /// 构造函数
            /// 用于从二进制数据读入区块
            /// </summary>
            /// <param name="fStream">要保存的文件流</param>
            /// <param name="ReceivedData">输入的二进制数据</param>
            public FileBlock(FileTransmission TransmissionTask, byte[] ReceivedData)
            {
                _Task = TransmissionTask;
                _FileStream = _Task.FileStream;
                if (ReceivedData[0] != Consts.FileBlockHeader)
                    throw new FileBlockException("Bad Header!", FileBlockException.ErrorCode.BadHeader);
                Index = BitConverter.ToInt32(ReceivedData, 1);
                _DataLength = ReceivedData.Length - 9;
                if (_DataLength > Consts.BlockSize)
                    throw new FileBlockException("Illegal FileBlock Size!", FileBlockException.ErrorCode.IllegalFileBlockSize);
                _Data = new byte[_DataLength];
                _DataHash = new byte[4];
                System.Array.Copy(ReceivedData, 5, _DataHash, 0, 4);
                System.Array.Copy(ReceivedData, 9, _Data, 0, _DataLength);
                if (!_DataHash.BytesEqual(_Data.GetHash()))
                    throw new FileBlockException("Error Hash!", FileBlockException.ErrorCode.ChecksumError);
            }
            /// <summary>
            /// 从文件读入
            /// </summary>
            /// <param name="CalcHashAfterRead">是否在读取后立即计算校验值</param>
            /// <returns>读取块的大小</returns>
            public int Read(bool CalcHashAfterRead)
            {
                _Data = new byte[Consts.BlockSize];
                lock (_FileStream)
                {
                    _FileStream.Position = (long)Index * (long)Consts.BlockSize;
                    _DataLength = _FileStream.Read(_Data, 0, Consts.BlockSize);
                }
                if (_Data.Length != _DataLength)
                {
                    byte[] old = _Data;
                    _Data = new byte[_DataLength];
                    System.Array.Copy(old, _Data, _DataLength);
                }
                if (CalcHashAfterRead)
                    CalcHash();
                return _DataLength;
            }
            /// <summary>
            /// 计算校验值
            /// </summary>
            /// <returns>校验值</returns>
            public byte[] CalcHash()
            {
                return _DataHash = _Data.GetHash();
            }
            /// <summary>
            /// 将该区块写入文件
            /// </summary>
            public void Write()
            {
                lock (_FileStream)
                {
                    _FileStream.Position = (long)Index * (long)Consts.BlockSize;
                    _FileStream.Write(_Data, 0, _DataLength);
                }
            }
            /// <summary>
            /// 转化为二进制数据以传输
            /// </summary>
            /// <returns></returns>
            public byte[] GetBytes()
            {
                MemoryStream mStream = new MemoryStream(1 + 4 + 4 + _DataLength);
                byte[] Header = new byte[1] { Consts.FileBlockHeader };
                mStream.Write(Header, 0, 1);
                mStream.Write(BitConverter.GetBytes(Index), 0, 4);
                mStream.Write(_DataHash, 0, 4);
                mStream.Write(_Data, 0, _DataLength);
                return mStream.ToArray();
            }
            int System.IComparable<FileBlock>.CompareTo(FileBlock obj)
            {
                return (Index as IComparable<int>).CompareTo(obj.Index);
            }
        }
        #endregion
    
        #region 事件参数类
        public class BlockFinishedEventArgs : EventArgs
        {
            public int BlockIndex { get; set; }
            public BlockFinishedEventArgs(int BlockIndex) { this.BlockIndex = BlockIndex; }
        }
        public class CommandReceivedEventArgs : EventArgs
        {
            public string CommandLine { get; set; }
            public CommandReceivedEventArgs(string CommandLine) { this.CommandLine = CommandLine; }
        }
        public class FileTransmissionErrorOccurEventArgs : EventArgs
        {
            public Exception InnerException { get; set; }
            /// <summary>
            /// 指示是否继续运行
            /// </summary>
            public bool Continue { get; set; }
            public FileTransmissionErrorOccurEventArgs(Exception innerException)
            {
                InnerException = innerException;
                Continue = false;
            }
        }
        #endregion
    
        #region 文件区块抽象集合类
        /// <summary>
        /// 文件区块的抽象集合
        /// 之所以说抽象是因为该集合并不存储实际的区块(缓存区除外)
        /// 而是通过一个索引器来读写文件
        /// 并提供磁盘缓存
        /// </summary>
        public class FileBlockCollection
        {
            /// <summary>
            /// 与该区块关联的传输对象
            /// </summary>
            internal FileTransmission _Task;
            /// <summary>
            /// 与该区块关联的FileStream
            /// </summary>
            internal FileStream _FileStream;
            internal bool _EnabledIOBuffer;
            /// <summary>
            /// 磁盘缓存区
            /// </summary>
            internal Dictionary<int, FileBlock> _IOBuffer;
    
            public FileBlockCollection(FileTransmission TransmissionTask)
            {
                _Task = TransmissionTask;
                _FileStream = _Task.FileStream;
                _IOBufferSize = Consts.DefaultIOBufferSize;
            }
            /// <summary>
            /// 获取或设置一个值,该值指示是否启用磁盘缓存
            /// </summary>
            internal bool EnabledIOBuffer
            {
                get { return _EnabledIOBuffer; }
                set
                {
                    _EnabledIOBuffer = value;
                    if (value)
                        _IOBuffer = new Dictionary<int, FileBlock>();
                    else
                    {
                        if (_Task is FileReceiver)
                            WriteAllBlock();
                        _IOBuffer = null;
                    }
                }
            }
            internal int _IOBufferSize;
            /// <summary>
            /// 获取已接收或已发送的区块序号列表
            /// </summary>
            public List<int> Finished { get { return _Task._FinishedBlock; } }
            /// <summary>
            /// 获取已存在(Hash成功)的区块序号列表
            /// </summary>
            public List<int> Exist
            {
                get
                {
                    if (_Task is FileReceiver)
                        return ((FileReceiver)_Task)._ExistBlock;
                    else
                        return null;
                }
            }
            /// <summary>
            /// 获取被丢弃的区块序号列表
            /// </summary>
            public List<int> Cast
            {
                get
                {
                    if (_Task is FileReceiver)
                        return ((FileReceiver)_Task)._CastBlock;
                    else
                        return null;
                }
            }
            /// <summary>
            /// 获取总区块数
            /// </summary>
            public int Count { get { return _Task._TotalBlock; } }
            /// <summary>
            /// 获取有效区块数(已存在+已接收)
            /// </summary>
            public int CountValid
            {
                get
                {
                    if (_Task is FileReceiver)
                        return _Task._FinishedBlock.Count + ((FileReceiver)_Task)._ExistBlock.Count;
                    else
                        return _Task._FinishedBlock.Count;
    
                }
            }
            /// <summary>
            /// 将缓存中的区块全部写入磁盘
            /// </summary>
            /// <returns>写入的区块数量</returns>
            public int WriteAllBlock()
            {
                if (!_EnabledIOBuffer)
                    return -1;
                int count = 0;
                lock (_IOBuffer)
                {
                    foreach (var b in _IOBuffer)
                    {
                        b.Value.Write();
                        count++;
                    }
                    if (count != _IOBuffer.Count)
                        throw new IOException("Can not Write All FileBlocks!");
                    _IOBuffer.Clear();
                }
                return count;
            }
            /// <summary>
            /// 读取数据以填充缓存
            /// </summary>
            /// <param name="StartIndex">起始区块</param>
            /// <returns>读取的区块数量</returns>
            public int FillIOBuffer(int StartIndex)
            {
                int Index;
                lock (_IOBuffer)
                {
                    _IOBuffer.Clear();
                    for (Index = StartIndex; _IOBuffer.Count < _IOBufferSize && Index < _Task.Blocks.Count; Index++)
                    {
                        _IOBuffer.Add(Index, new FileBlock(_Task, Index, true));
                    }
                }
                return Index - StartIndex;
            }
            /// <summary>
            /// 异步填充缓存
            /// </summary>
            /// <param name="StartIndex">起始区块</param>
            public IAsyncResult BeginFillIOBuffer(int StartIndex,AsyncCallback callback,object state)
            {
                return new Delegate_Int_Int(FillIOBuffer).BeginInvoke(StartIndex, callback, state);
            }
            /// <summary>
            /// 写入区块
            /// </summary>
            /// <param name="value">区块对象</param>
            public void Write(FileBlock value)
            {
                if (_EnabledIOBuffer)
                {
                    if (_IOBuffer.Count >= _IOBufferSize)
                        WriteAllBlock();
                    lock (_IOBuffer)
                        _IOBuffer.Add(value.Index, value);
                }
                else
                    value.Write();
            }
            /// <summary>
            /// 读取或写入区块
            /// </summary>
            /// <param name="BlockIndex">区块序号</param>
            public FileBlock this[int BlockIndex]
            {
                get
                {
                    FileBlock output;
                    if (_EnabledIOBuffer)
                    {
                        
                        bool IsInBuf;
                        lock (_IOBuffer)
                            IsInBuf = _IOBuffer.TryGetValue(BlockIndex, out output);
                        if (IsInBuf)
                            return output;
                        else
                        {
                            output = new FileBlock(_Task, BlockIndex, true);
                            BeginFillIOBuffer(BlockIndex + 1, null, null);
                        }
                    }
                    else
                        output = new FileBlock(_Task, BlockIndex, true);
                    return output;
                }
                set
                {
                    if (BlockIndex != value.Index)
                        throw new FileBlockException("Bad Index!", FileBlockException.ErrorCode.BadIndex);
                    Write(value);
                }
            }
        }
        #endregion
    
        #region 文件传输基类
        public abstract class FileTransmission : IDisposable
        {
            internal FileStream _FileStream;
            //internal readonly TransmissionMode _Mode;
            /// <summary>
            /// 总区块数
            /// </summary>
            internal int _TotalBlock;
            /// <summary>
            /// 最后一个区块的大小
            /// </summary>
            internal int _LastBlockSize;
            internal List<int> _FinishedBlock;
            internal byte[] ReceiveBuf;
            internal Socket _Socket;
            internal EventWaitHandle _WaitHandle;
            internal bool _IsAlive;
            internal FileBlockCollection _Blocks;
            internal DateTime _StartTime;
            /// <summary>
            /// 上一个区块完成的时间
            /// </summary>
            internal DateTime _PriorBlockTime;
            internal double _ByteSpeed;
            /// <summary>
            /// 获取或设置一个值,该值指示是否启用磁盘缓存
            /// </summary>
            public bool EnabledIOBuffer
            {
                get { return _Blocks._EnabledIOBuffer; }
                set { _Blocks.EnabledIOBuffer = value; }
            }
            /// <summary>
            /// 获取或设置磁盘缓存的大小(单位:区块数)
            /// </summary>
            public int IOBufferSize
            {
                get { return _Blocks._IOBufferSize; }
                set
                {
                    if (!_Blocks._EnabledIOBuffer)
                        throw new InvalidOperationException("IOBuffer is not enabled!");
                    _Blocks._IOBufferSize = value;
                }
            }
            /// <summary>
            /// 获取当前磁盘缓存中的区块数
            /// </summary>
            public int CurrentIOBufferSize
            {
                get
                {
                    if (!_Blocks._EnabledIOBuffer)
                        return 0;
                    return _Blocks._IOBuffer.Count;
                }
            }
            /// <summary>
            /// 获取或设置该传输的目标连接
            /// </summary>
            public Socket Socket
            {
                get { return _Socket; }
                set
                {
                    try
                    {
                        if (value.ProtocolType != ProtocolType.Tcp)
                            throw new ArgumentException("Socket Protocol must be TCP", "Socket");
                        _Socket = value;
                        _Socket.ReceiveBufferSize = _Socket.SendBufferSize = Consts.NetBlockMaxSize;
                    }
                    catch (Exception ex)
                    {
                        OnErrorOccurred(ex);
                    }
                }
            }
            /// <summary>
            /// 获取与此传输关联的文件流
            /// </summary>
            public FileStream FileStream { get { return _FileStream; } }
            /// <summary>
            /// 获取或设置文件路径
            /// </summary>
            public string FilePath { get; set; }
            /// <summary>
            /// 获取或设置文件名
            /// </summary>
            public string FileName { get; set; }
            /// <summary>
            /// 获取或设置文件名(包括路径)
            /// </summary>
            public string FullFileName
            {
                get
                {
                    try
                    {
                        return FilePath.TrimEnd('\\') + "\\" + FileName;
                    }
                    catch (Exception ex)
                    {
                        OnErrorOccurred(ex);
                        return null;
                    }
                }
                set
                {
                    try
                    {
                        int i = value.LastIndexOf('\\');
                        if (i > 0)
                            FilePath = value.Substring(0, i);
                        else
                            FilePath = Environment.CurrentDirectory;
                        FileName = value.Substring(i + 1);
                    }
                    catch (Exception ex)
                    {
                        OnErrorOccurred(ex);
                    }
                }
            }
            /// <summary>
            /// 一个区块完成时发生
            /// </summary>
            public event BlockFinishedEventHandler BlockFinished;
            /// <summary>
            /// 全部完成时发生
            /// </summary>
            public event EventHandler AllFinished;
            /// <summary>
            /// 连接中断时发生
            /// </summary>
            public event EventHandler ConnectLost;
            /// <summary>
            /// 出现错误时发生
            /// </summary>
            public event FileTransmissionErrorOccurEventHandler ErrorOccurred;
            /// <summary>
            /// 获取一个值,该值指示传输是否正在进行
            /// </summary>
            public bool IsAlive { get { return _IsAlive; } }
            /// <summary>
            /// 获取传输开始的时间
            /// </summary>
            public DateTime StartTime { get { return _StartTime; } }
            /// <summary>
            /// 获取已用时
            /// </summary>
            public TimeSpan TimePast { get { return DateTime.Now - _StartTime; } }
            /// <summary>
            /// 获取估计剩余时间
            /// </summary>
            public abstract TimeSpan TimeRemaining { get; }
            /// <summary>
            /// 获取平均速率(区块/秒)
            /// </summary>
            public double BlockAverSpeed
            {
                get
                {
                    return _FinishedBlock.Count / TimePast.TotalSeconds;
                }
            }
            /// <summary>
            /// 获取平均速率(字节/秒)
            /// </summary>
            public double ByteAverSpeed
            {
                get
                {
                    return BlockAverSpeed * Consts.BlockSize;
                }
            }
            /// <summary>
            /// 获取平均速率(千字节/秒)
            /// </summary>
            public double KByteAverSpeed
            {
                get
                {
                    return ByteAverSpeed / 1024;
                }
            }
            /// <summary>
            /// 获取瞬时速率(字节/秒)
            /// </summary>
            public double ByteSpeed
            {
                get
                {
                    return _ByteSpeed;
                }
            }
            /// <summary>
            /// 获取瞬时速率(千字节/秒)
            /// </summary>
            public double KByteSpeed
            {
                get
                {
                    return _ByteSpeed / 1024;
                }
            }
            /// <summary>
            /// 获取文件总长度
            /// </summary>
            public long TotalSize
            {
                get
                {
                    return (long)(_TotalBlock - 1) * (long)Consts.BlockSize + (long)_LastBlockSize;
                }
            }
            /// <summary>
            /// 获取已完成的数据长度
            /// </summary>
            public abstract long FinishedSize { get; }
            /// <summary>
            /// 获取进度值(%)
            /// </summary>
            public double Progress
            {
                get
                {
                    return ((double)FinishedSize / (double)TotalSize) * 100;
                }
            }
            /// <summary>
            /// 获取该传输的区块集合
            /// </summary>
            public FileBlockCollection Blocks { get { return _Blocks; } }
            /// <summary>
            /// 默认构造函数
            /// </summary>
            public FileTransmission()
            {
                _FinishedBlock = new List<int>();
                _WaitHandle = new EventWaitHandle(false, EventResetMode.ManualReset);
                _Blocks = new FileBlockCollection(this);
            }
            /// <summary>
            /// 构造函数
            /// </summary>
            /// <param name="FilePath">文件路径</param>
            /// <param name="FileName">文件名</param>
            public FileTransmission(string FilePath, string FileName)
            {
                _FinishedBlock = new List<int>();
                _WaitHandle = new EventWaitHandle(true, EventResetMode.ManualReset);
                _Blocks = new FileBlockCollection(this);
    
                this.FilePath = FilePath;
                this.FileName = FileName;
            }
            /// <summary>
            /// 初始化接收缓存
            /// </summary>
            internal void InitializeReceiveBuf()
            {
                try
                {
                    ReceiveBuf = new byte[_Socket.ReceiveBufferSize];
                }
                catch (Exception ex)
                {
                    OnErrorOccurred(ex);
                }
            }
            /// <summary>
            /// 开始异步接收
            /// </summary>
            internal abstract IAsyncResult BeginReceive();
            /// <summary>
            /// 开始传输
            /// </summary>
            public virtual void Start()
            {
                try
                {
                    _IsAlive = true;
                    _StartTime = DateTime.Now;
                    _WaitHandle.Reset();
                }
                catch (Exception ex)
                {
                    OnErrorOccurred(ex);
                }
            }
            /// <summary>
            /// 中止传输
            /// </summary>
            /// <param name="ShutDownSocket">是否关闭Socket</param>
            public virtual void Stop(bool ShutDownSocket)
            {
                try
                {
                    _IsAlive = false;
                    _FileStream.Close();
                    _FileStream = null;
                    _WaitHandle.Set();
                    if (ShutDownSocket)
                    {
                        _Socket.Shutdown(SocketShutdown.Both);
                        _Socket.Close();
                    }
                }
                catch (Exception ex)
                {
                    OnErrorOccurred(ex);
                }
            }
            /// <summary>
            /// 异步中止传输,不关闭Socket
            /// </summary>
            internal void Stop()
            {
                new Delegate_Void_Bool(Stop).BeginInvoke(false, null, null);
            }
            /// <summary>
            /// 等待传输完成
            /// </summary>
            public bool WaitForExit()
            {
                return _WaitHandle.WaitOne();
            }
            /// <summary>
            /// 等待传输完成
            /// </summary>
            public bool WaitForExit(int millisecondsTimeout, bool exitContext)
            {
                return _WaitHandle.WaitOne(millisecondsTimeout, exitContext);
            }
            /// <summary>
            /// 等待传输完成
            /// </summary>
            public bool WaitForExit(TimeSpan timeout, bool exitContext)
            {
                return _WaitHandle.WaitOne(timeout, exitContext);
            }
            internal virtual void OnBlockFinished(int BlockIndex)
            {
                if (!_FinishedBlock.Exists(a => a == BlockIndex))
                    _FinishedBlock.Add(BlockIndex);
                if (BlockIndex == _TotalBlock - 1)
                    _ByteSpeed = _LastBlockSize / (DateTime.Now - _PriorBlockTime).TotalSeconds;
                else
                    _ByteSpeed = Consts.BlockSize / (DateTime.Now - _PriorBlockTime).TotalSeconds;
                _PriorBlockTime = DateTime.Now;
                if (BlockFinished != null)
                    BlockFinished(this, new BlockFinishedEventArgs(BlockIndex));
            }
            internal virtual void OnConnectLost()
            {
                if (!_IsAlive)
                    return;
                Stop();
                if (ConnectLost != null)
                    ConnectLost(this, new EventArgs());
            }
            /// <summary>
            /// 同步发送字符串
            /// </summary>
            public int SendString(string str)
            {
                try
                {
                    return _Socket.EndSend(BeginSendString(str, null, null));
                }
                catch (SocketException)
                {
                    OnConnectLost();
                    return 0;
                }
                catch (Exception ex)
                {
                    OnErrorOccurred(ex);
                    return 0;
                }
            }
            /// <summary>
            /// 异步发送字符串并使用默认的回调方法
            /// </summary>
            public void SendStringAsync(string str)
            {
                BeginSendString(str, SendCallback, null);
            }
            /// <summary>
            /// 异步发送字符串并使用指定的的回调方法和参数
            /// </summary>
            public IAsyncResult BeginSendString(string str, AsyncCallback callback, object state)
            {
                try
                {
                    if (!_IsAlive)
                        throw new InvalidOperationException("Is Not Alive");
                    byte[] ToSend = str.ToBytes();
                    return _Socket.BeginSend(ToSend, 0, ToSend.Length, SocketFlags.None, callback, state);
                }
                catch (SocketException)
                {
                    OnConnectLost();
                    return null;
                }
                catch (Exception ex)
                {
                    OnErrorOccurred(ex);
                    return null;
                }
            }
            internal void SendCallback(IAsyncResult ar)
            {
                try
                {
                    _Socket.EndSend(ar);
                }
                catch (SocketException)
                {
                    OnConnectLost();
                }
                catch (Exception ex)
                {
                    OnErrorOccurred(ex);
                }
                if (ar.AsyncState != null)
                {
                    if (ar.AsyncState is int)
                    {
                        OnBlockFinished((int)ar.AsyncState);
                    }
                }
            }
            internal virtual void OnAllFinished()
            {
                if (AllFinished != null)
                    AllFinished(this, new EventArgs());
            }
            internal virtual void OnErrorOccurred(Exception innerException)
            {
                FileTransmissionErrorOccurEventArgs eventargs = new FileTransmissionErrorOccurEventArgs(innerException);
                if (ErrorOccurred != null)
                    ErrorOccurred(this, eventargs);
                if (!eventargs.Continue)
                    throw innerException;
            }
            void System.IDisposable.Dispose()
            {
                _FileStream.Close();
                _Socket.Close();
            }
        }
        #endregion
    
        #region 发送端类
        /// <summary>
        /// 发送端
        /// 传输前发送端创建该类实例
        /// 设置必要属性后
        /// 调用Start()方法开始传输
        /// </summary>
        public class FileSender : FileTransmission
        {
            /// <summary>
            /// 接收到命令时发生
            /// </summary>
            public event CommandReceivedEventHandler CommandReceived;
            /// <summary>
            /// 开始异步接收
            /// </summary>
            internal override IAsyncResult BeginReceive()
            {
                InitializeReceiveBuf();
                try
                {
                    return _Socket.BeginReceive(ReceiveBuf, 0, ReceiveBuf.Length, SocketFlags.None, ReceiveCallback, null);
                }
                catch (SocketException)
                {
                    OnConnectLost();
                    return null;
                }
                catch (Exception ex)
                {
                    OnErrorOccurred(ex);
                    return null;
                }
            }
            /// <summary>
            /// 开始传输
            /// </summary>
            public override void Start()
            {
                base.Start();
                try
                {
                    BeginReceive();
                    _FileStream = new FileStream(FullFileName, FileMode.Open, FileAccess.Read, FileShare.Read);
                    _TotalBlock = (int)(_FileStream.Length / (long)Consts.BlockSize) + 1;
                    _LastBlockSize = (int)(_FileStream.Length - ((long)_TotalBlock - 1) * (long)Consts.BlockSize);
                }
                catch (Exception ex)
                {
                    OnErrorOccurred(ex);
                }
            }
            /// <summary>
            /// 获取估计剩余时间
            /// </summary>
            public override TimeSpan TimeRemaining
            {
                get
                {
                    int BlockRemaining = _TotalBlock - _FinishedBlock.Count;
                    return TimeSpan.FromSeconds(BlockRemaining / BlockAverSpeed);
                }
            }
            /// <summary>
            /// 获取已完成的数据长度
            /// </summary>
            public override long FinishedSize
            {
                get
                {
                    return (long)_FinishedBlock.Count * (long)Consts.BlockSize;
                }
            }
            /// <summary>
            /// 同步发送区块
            /// </summary>
            /// <param name="BlockIndex">区块序号</param>
            /// <returns>发送的数据长度</returns>
            public int SendBlock(int BlockIndex)
            {
                try
                {
                    int ret = _Socket.EndSend(BeginSendBlock(BlockIndex, null, null));
                    OnBlockFinished(BlockIndex);
                    return ret;
                }
                catch (SocketException)
                {
                    OnConnectLost();
                    return 0;
                }
                catch (Exception ex)
                {
                    OnErrorOccurred(ex);
                    return 0;
                }
            }
            /// <summary>
            /// 异步发送区块并使用默认的回调方法
            /// </summary>
            /// <param name="BlockIndex">区块序号</param>
            public void SendBlockAsync(int BlockIndex)
            {
                BeginSendBlock(BlockIndex, SendCallback, BlockIndex);
            }
            /// <summary>
            /// 异步发送区块并使用指定的回调方法和参数
            /// </summary>
            /// <param name="BlockIndex">区块序号</param>
            public IAsyncResult BeginSendBlock(int BlockIndex, AsyncCallback callback, object state)
            {
                try
                {
                    if (!_IsAlive)
                        throw new InvalidOperationException("Is Not Alive");
                    if (BlockIndex >= _TotalBlock)
                        throw new ArgumentOutOfRangeException("BlockIndex");
                    byte[] ToSend = _Blocks[BlockIndex].GetBytes();
                    return _Socket.BeginSend(ToSend, 0, ToSend.Length, SocketFlags.None, callback, state);
                }
                catch (SocketException)
                {
                    OnConnectLost();
                    return null;
                }
                catch (Exception ex)
                {
                    OnErrorOccurred(ex);
                    return null;
                }
            }
            internal void ReceiveCallback(IAsyncResult ar)
            {
                bool ContinueReceive = true;
                int count = 0;
                try
                {
                    count = _Socket.EndReceive(ar);
                }
                catch (SocketException)
                {
                    OnConnectLost();
                    return;
                }
                catch (Exception ex)
                {
                    try
                    {
                        OnErrorOccurred(ex);
                    }
                    catch { return; }
                }
                try
                {
                    if (count == 0)
                        return;
                    switch (ReceiveBuf[0])
                    {
                        case Consts.StringHeader:
                            ContinueReceive = OnCommandReceived(ReceiveBuf.ToFTString());
                            break;
                        default:
                            throw new FormatException("Bad Header!");
                    }
                }
                catch (Exception ex)
                {
                    OnErrorOccurred(ex);
                }
                if (ContinueReceive)
                {
                    BeginReceive();
                }
            }
            /// <summary>
            /// 命令处理
            /// </summary>
            /// <param name="str">收到的命令</param>
            /// <returns>是否继续接收</returns>
            internal bool OnCommandReceived(string str)
            {
                if (CommandReceived != null)
                    CommandReceived(this, new CommandReceivedEventArgs(str));
                bool ContinueReceive = true;
                string[] Msg = str.Split(' ');
                if (Msg[0] == "Exit")
                {
                    OnAllFinished();
                    ContinueReceive = false;
                    Stop();
                }
                else if (Msg[0] == "GET")
                {
                    if (Msg[1] == "FileBlock")
                    {
                        int BlockIndex;
                        if (!int.TryParse(Msg[2], out BlockIndex))
                            throw new FormatException("Bad BlockIndex " + Msg[2]);
                        SendBlock(BlockIndex);
                    }
                    else if (Msg[1] == "BlockHash")
                    {
                        int BlockIndex;
                        if (!int.TryParse(Msg[2], out BlockIndex))
                            throw new FormatException("Bad BlockIndex " + Msg[2]);
                        byte[] hash = _Blocks[BlockIndex].DataHash;
                        SendStringAsync(string.Format("BlockHash {0} {1}", BlockIndex, BitConverter.ToInt32(hash, 0)));
                    }
                    else if (Msg[1] == "FileName")
                    {
                        SendStringAsync(string.Format("SET FileName {0}", FileName.DoReplace()));
                    }
                    else if (Msg[1] == "TotalBlock")
                    {
                        SendStringAsync(string.Format("SET TotalBlock {0}", _TotalBlock));
                    }
                    else if (Msg[1] == "LastBlockSize")
                    {
                        SendStringAsync(string.Format("SET LastBlockSize {0}", _LastBlockSize));
                    }
                    else
                        throw new FormatException("Bad Command " + Msg[1]);
                }
                else
                    throw new FormatException("Bad Command " + Msg[0]);
    
                return ContinueReceive;
            }
        }
        #endregion
    
        #region 接收端类
        /// <summary>
        /// 接收端
        /// 传输前接收端创建该类实例
        /// 设置必要属性后
        /// 调用Start()方法开始传输
        /// </summary>
        public class FileReceiver : FileTransmission
        {
            internal List<int> _ExistBlock;
            internal List<int> _CastBlock;
            /// <summary>
            /// 下载线程
            /// </summary>
            internal Thread _DownThread;
            public event BlockFinishedEventHandler BlockHashed;
            /// <summary>
            /// 开始异步接收
            /// </summary>
            internal override IAsyncResult BeginReceive()
            {
                InitializeReceiveBuf();
                try
                {
                    return _Socket.BeginReceive(ReceiveBuf, 0, ReceiveBuf.Length, SocketFlags.None, null, null);
                }
                catch (SocketException)
                {
                    OnConnectLost();
                    return null;
                }
                catch (Exception ex)
                {
                    OnErrorOccurred(ex);
                    return null;
                }
            }
            /// <summary>
            /// 获取估计剩余时间
            /// </summary>
            public override TimeSpan TimeRemaining
            {
                get
                {
                    int BlockRemaining = _TotalBlock - _FinishedBlock.Count - ((FileReceiver)this)._ExistBlock.Count;
                    return TimeSpan.FromSeconds(BlockRemaining / BlockAverSpeed);
                }
            }
            /// <summary>
            /// 获取已完成的数据长度
            /// </summary>
            public override long FinishedSize
            {
                get
                {
                    return ((long)_FinishedBlock.Count + (long)_ExistBlock.Count - 1) * (long)Consts.BlockSize + (long)_LastBlockSize;
                }
            }
            /// <summary>
            /// 开始传输
            /// </summary>
            public override void Start()
            {
                base.Start();
                try
                {
                    _CastBlock = new List<int>();
                    _ExistBlock = new List<int>();
                    _DownThread = new Thread(DownLoad);
                    _DownThread.IsBackground = true;
                    _DownThread.Name = "DownThread";
                    _DownThread.Start();
                }
                catch (Exception ex)
                {
                    OnErrorOccurred(ex);
                }
            }
            /// <summary>
            /// 中止传输
            /// </summary>
            /// <param name="ShutDownSocket">是否关闭Socket</param>
            public override void Stop(bool ShutDownSocket)
            {
                try
                {
                    if (_DownThread != null)
                    {
                        if ((_DownThread.ThreadState & ThreadState.Running) == ThreadState.Running)
                            _DownThread.Abort();
                    }
                }
                catch (Exception ex)
                {
                    OnErrorOccurred(ex);
                }
                base.Stop(ShutDownSocket);
            }
            internal string ReceiveString()
            {
                int count = 0;
                try
                {
                    count = _Socket.EndReceive(BeginReceive());
                }
                catch (Exception ex)
                {
                    OnConnectLost();
                    throw ex;
                }
                if (count == 0)
                    return null;
                else
                    return ReceiveBuf.ToFTString();
            }
            internal FileBlock ReceiveFileBlock()
            {
                MemoryStream mStream = new MemoryStream();
                while (true)
                {
                    int count = 0;
                    try
                    {
                        count = _Socket.EndReceive(BeginReceive());
                        if (count == 0) throw new Exception();
                    }
                    catch (Exception ex)
                    {
                        OnConnectLost();
                        throw ex;
                    }
                    mStream.Write(ReceiveBuf, 0, count);
                    try
                    {//接收到正确的区块则返回
                        return new FileBlock(this, mStream.ToArray());
                    }
                    catch (FileBlockException ex)
                    {//接收到不完整或错误的区块,若不完整则继续接收
                        if (mStream.Length >= Consts.NetBlockMaxSize)
                            throw ex;//区块已达到指定大小但仍然错误,则抛出错误
                    }
                }
            }
            /// <summary>
            /// 从发送端获取文件名
            /// </summary>
            public void GetFileName()
            {
                while (true)
                {
                    SendString("GET FileName");
                    string[] Msg = ReceiveString().Split(' ');
                    if (Msg[0] == "SET" && Msg[1] == "FileName")
                    {
                        FileName = Msg[2];
                        break;
                    }
                }
            }
            /// <summary>
            /// 从发送端获取区块总数
            /// </summary>
            public void GetTotalBlock()
            {
                while (true)
                {
                    SendString("GET TotalBlock");
                    string[] Msg = ReceiveString().Split(' ');
                    if (Msg[0] == "SET" && Msg[1] == "TotalBlock")
                    {
                        if (int.TryParse(Msg[2], out _TotalBlock))
                            break;
                    }
                }
            }
            /// <summary>
            /// 从发送端获取最后一个区块的大小
            /// </summary>
            public void GetLastBlockSize()
            {
                while (true)
                {
                    SendString("GET LastBlockSize");
                    string[] Msg = ReceiveString().Split(' ');
                    if (Msg[0] == "SET" && Msg[1] == "LastBlockSize")
                    {
                        if (int.TryParse(Msg[2], out _LastBlockSize))
                            break;
                    }
                }
            }
            /// <summary>
            /// 校验文件
            /// </summary>
            /// <returns>损坏或尚未下载的区块序号列表</returns>
            public List<int> HashFile()
            {
                _FileStream.Position = 0;
                _ExistBlock.Clear();
                for (int count = 0; _FileStream.Position < _FileStream.Length && count < _TotalBlock; count++)
                {//校验已存在的区块
                    FileBlock TestBlock = new FileBlock(this, count, true);
                    SendString(string.Format("GET BlockHash {0}", count));
                    string[] Msg = ReceiveString().Split(' ');
                    if (Msg[0] == "BlockHash")
                    {
                        if (Convert.ToInt32(Msg[1]) == count)
                        {
                            if (BitConverter.ToInt32(TestBlock.DataHash, 0) == Convert.ToInt32(Msg[2]))
                                _ExistBlock.Add(count);
                        }
                    }
                    if (BlockHashed != null)
                        BlockHashed(this, new BlockFinishedEventArgs(count));
                }
                int MaxExistBlockIndex;//已存在的区块最大序号
                try
                {
                    MaxExistBlockIndex = _ExistBlock.Max();
                }
                catch
                {
                    MaxExistBlockIndex = 0;
                }
                List<int> BlockRemaining = new List<int>();
                for (int index = 0; index < _TotalBlock; )
                {//计算仍需传输的区块
                    if (index <= MaxExistBlockIndex)
                    {
                        if (_ExistBlock.Exists(a => a == index))
                        {
                            index++;
                            continue;
                        }
                    }
                    BlockRemaining.Add(index++);
                }
                return BlockRemaining;
            }
            /// <summary>
            /// 接收整个文件
            /// </summary>
            internal void DownLoad()
            {
                try
                {
                    if (string.IsNullOrEmpty(FilePath))//未指定路径时默认为接收程序所在路径
                        FilePath = Environment.CurrentDirectory;
                    if (string.IsNullOrEmpty(FileName))//未指定文件名时从发送端获取
                    {
                        GetFileName();
                    }
                    _FileStream = new FileStream(FullFileName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);//temp
                    GetTotalBlock();
                    GetLastBlockSize();
                    List<int> BlockRemaining = HashFile();
                    if (_FileStream.Length > TotalSize)//如果已存在的文件比目标文件长则截断它
                        _FileStream.SetLength(TotalSize);
                    _StartTime = DateTime.Now;
                    foreach (int index in BlockRemaining)
                    {
                        FileBlock Block;
                        while (true)
                        {
                            SendString(string.Format("GET FileBlock {0}", index));
                            try
                            {
                                Block = ReceiveFileBlock();
                                break;
                            }
                            catch (FileBlockException)
                            {//接收到错误的区块,抛弃该数据并重新请求
                                _CastBlock.Add(index);
                            }
                            catch (Exception ex)
                            {
                                OnErrorOccurred(ex);
                            }
                        }
                        while (true)
                        {
                            try
                            {
                                _Blocks[index] = Block;//写入区块
                                OnBlockFinished(index);
                                break;
                            }
                            catch (IOException ex)
                            {//磁盘写入错误时
                                try
                                {
                                    OnErrorOccurred(ex);
                                    //重试
                                }
                                catch
                                {//退出
                                    Stop();
                                    return;
                                }
                            }
                            catch (Exception ex)
                            {
                                OnErrorOccurred(ex);
                            }
                        }
                    }
                    SendStringAsync("Exit");
                    _Blocks.WriteAllBlock();
                    OnAllFinished();
                    Stop();
                }
                catch (SocketException) { }
                catch (Exception ex)
                {
                    OnErrorOccurred(ex);
                }
            }
        }
        #endregion
    }

    VS2008完整项目文件,包括类库和一个简单的Demo:
    /Files/takamachi660/SendFileTest_v0.6.rar

    =========================

    using System;
    using log4net;
    using System.Collections;
    using System.Text;
    using System.IO;
    using System.Net;
    using log4net.Config;
    using Chxp.Business;
    namespace Chxp.Service
    {
       public class FileLib
        {
            #region 属性
            private string fileName = "";
            public string FileName
            {
                get { return fileName; }
                set { fileName = value; }
            }
          
            #endregion  
          
           private static readonly ILog LOG = LogManager.GetLogger(typeof(FileLib));
    
            #region 文件上传
           
           /// <summary>
           /// 上传文件(自动分割)
           /// </summary>
           /// <param name="filePath">待上传的文件全路径名称(@"E:/FTP/ftproot/20070228DQCK.zip")</param>
           /// <param name="hostURL">服务器的地址</param>
           /// <param name="byteCount">分割的字节大小</param>        
           /// <param name="userID">主机用户ID</param>
           /// <param name="cruuent">当前字节指针</param>
           /// <returns>成功返回"";失败则返回错误信息</returns>
            public string UpLoadFile(string filePath, string hostURL, int byteCount,string userID,long cruuent)
            {
                string tmpURL = hostURL;
                byteCount = byteCount * 1024;
                //http://localhost:8080/fism/app?service=fileupload&beanId=com.cfcc.fism.service.upload.CollFileSaveServiceImpl&action=upload&filename=AI1215900000020051130411.zip&userid=test&npos=333
                //action=length
    
                System.Net.WebClient WebClientObj = new System.Net.WebClient();
                FileStream fStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
                BinaryReader bReader = new BinaryReader(fStream);
                long length = fStream.Length;           
                string sMsg = "版式上传成功";
                string fileName = filePath.Substring(filePath.LastIndexOf('//') + 1);           
                try
                {
    
                    #region 续传处理
                    byte[] data;
                    if (cruuent > 0)
                    {
                        fStream.Seek(cruuent, SeekOrigin.Current);
                    }
                    #endregion 
    
                    #region 分割文件上传
                    for (; cruuent <= length; cruuent = cruuent + byteCount)
                    { 
                        if (cruuent + byteCount > length)
                        {
                            data = new byte[Convert.ToInt64((length - cruuent))];
                            bReader.Read(data, 0, Convert.ToInt32((length - cruuent)));
                        }
                        else
                        {
                            data = new byte[byteCount];
                            bReader.Read(data, 0, byteCount);
                        } 
                        try
                        { 
                            LOG.Debug(data); 
                            //***
                            hostURL = tmpURL + "&action=upload" + "&filename=" + fileName + "&userid=" + userID + "&npos=" + cruuent.ToString();
                            byte[] byRemoteInfo = WebClientObj.UploadData(hostURL, "POST", data);
                            string sRemoteInfo = System.Text.Encoding.Default.GetString(byRemoteInfo);
    
                          //  获取返回信息
                            if (sRemoteInfo.Trim() != "")
                            {
                                sMsg =  sRemoteInfo;
                                break; 
                            }
                        }
                        catch (Exception ex)
                        {
                            sMsg =  ex.ToString();
                            break;
                        }
                    #endregion
    
                    }
                }
                catch (Exception ex)
                {
                    sMsg = sMsg + ex.ToString(); 
                }
                try
                { 
                    bReader.Close();
                    fStream.Close();
                }
                catch (Exception exMsg)
                {
                    sMsg =  exMsg.ToString();
                } 
                GC.Collect();
                return sMsg;
            } 
            #endregion
    
            #region 获取文件大小
           /// <summary>
           /// 获取远程服务器文件字节大小
           /// </summary>
           /// <param name="filePath">待上传的文件全路径名称</param>
           /// <param name="hostURL">服务器的地址</param>
           /// <param name="userID">主机用户ID</param>
           /// <returns>远程文件大小</returns>
            public long GetRemoteFileLength(string filePath, string hostURL, string userID)
           {
               long length = 0; 
               System.Net.WebClient WebClientObj = new System.Net.WebClient();  
               string fileName = filePath.Substring(filePath.LastIndexOf('//') + 1); 
               hostURL = hostURL +"&action=length" + "&filename=" + fileName + "&userid=" + userID + "&npos=0" ;
               
               byte[] data = new byte[0];
               byte[] byRemoteInfo = WebClientObj.UploadData(hostURL , "POST", data);
               string sRemoteInfo = System.Text.Encoding.Default.GetString(byRemoteInfo);//主系统没有作异常处理
               try
               {
                   length = Convert.ToInt64(sRemoteInfo);
               }
               catch (Exception exx)
               {
                   LOG.Error("FileLib类GetRemoteFileLength()中length = Convert.ToInt64(sRemoteInfo)语句异常:" + exx.Message);//我们强制处理异常
                   length = 0;
               }
               GC.Collect(); 
               return length; 
           }
    
           /// <summary>
           /// 获得本地文件字节大小
           /// </summary>
           /// <param name="filePath">本地文件全路径</param>
           /// <returns>本地文件字节大小</returns>
           public long GetLocalFileLength(string filePath)
           {
               long length = 0;
               try
               {
                   string fileName = filePath.Substring(filePath.LastIndexOf('//') + 1);
                   FileStream s = new FileStream(filePath, FileMode.Open);
                   length = s.Length;
                   s.Close();
               }
               catch(Exception ex)
               {
                   LOG.Error("FileLib类中获取本地文件大小异常:"+ex.Message);
               }
               return length; 
           }
            #endregion
    
           #region 文件下载
           public bool DownLoadFile(string localPath, string hostURL, int byteCount, string userID, long cruuent)
           {
               bool result = true; 
               string tmpURL = hostURL;
              
               byteCount = byteCount * 1024;
               hostURL = tmpURL + "&npos=" + cruuent.ToString();
               
               System.IO.FileStream fs;  
               fs = new FileStream(localPath, FileMode.OpenOrCreate);
               if (cruuent > 0)
               {
                   //偏移指针
                   fs.Seek(cruuent, System.IO.SeekOrigin.Current); 
               } 
    
               System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(hostURL);
               if (cruuent > 0)
               {
                   request.AddRange(Convert.ToInt32(cruuent));    //设置Range值
               }
    
               try
               {
                   //向服务器请求,获得服务器回应数据流
                   System.IO.Stream ns = request.GetResponse().GetResponseStream();
    
                   byte[] nbytes = new byte[byteCount];
                   int nReadSize = 0;
                   nReadSize = ns.Read(nbytes, 0, byteCount);
                  
                   while (nReadSize > 0)
                   {
                       fs.Write(nbytes, 0, nReadSize);
                       nReadSize = ns.Read(nbytes, 0, byteCount); 
                   }
                   fs.Close();
                   ns.Close();
               }
               catch(Exception ex)
               {
                   LOG.Error("下载" + localPath + "的时候失败!" + "原因是:" + ex.Message);
                   fs.Close();
                   result = false;
               }  
               return result; 
           }
           #endregion 
       }
    }
  • 相关阅读:
    codevs 2833 奇怪的梦境
    codevs 3058 寻找sb5
    codevs 2989 寻找somebody
    并查集
    排列组合
    序章
    [POJ2625][UVA10288]Coupons
    2017NOIP模拟赛-科普基地
    AIM Tech Round 5 (rated, Div. 1 + Div. 2)
    浙江十套
  • 原文地址:https://www.cnblogs.com/oneLight/p/2523659.html
Copyright © 2020-2023  润新知